更多 C++ 惯用法/内部类
外观
- 在没有多重继承的情况下实现多个接口,并提供自然的外观向上转换。
- 在单个抽象中提供同一接口的多种实现。
两个独立类库提供的两个独立接口中的虚函数签名可能发生冲突。当一个类必须根据您考虑的接口以不同的方式实现这两个冲突函数时,这尤其是一个问题。例如,
class Base1 /// Provided by Moon
{
public:
virtual int open (int) = 0;
/* virtual */ ~Base1() {} // No polymorphic deletion allowed
};
class Base2 /// Provided by Jupitor
{
public:
virtual int open (int) = 0;
/* virtual */ ~Base2() {} // No polymorphic deletion allowed
};
class Derived : public Base1, public Base2
{
public:
virtual int open (int i)
{
// Call from which base class?
return 0;
}
/* virtual */ ~Derived () {}
};
内部类惯用法可以帮助解决此问题。
保持接口类 Base1 和 Base2 不变,我们可以如下实现 Derived 类。
#include <iostream>
class Base1 /// Provided by Moon
{
public:
virtual int open() = 0;
/* virtual */ ~Base1() {} // No polymorphic deletion allowed
};
class Base2 /// Provided by Jupitor
{
public:
virtual int open() = 0;
/* virtual */ ~Base2() {} // No polymorphic deletion allowed
};
class Derived // Note no inheritance
{
class Base1_Impl;
friend class Base1_Impl;
class Base1_Impl : public Base1 // Note public inheritance
{
public:
Base1_Impl(Derived* p) : parent_(p) {}
int open() override { return parent_->base1_open(); }
private:
Derived* parent_;
} base1_obj; // Note member object here.
class Base2_Impl;
friend class Base2_Impl;
class Base2_Impl : public Base2 // Note public inheritance
{
public:
Base2_Impl(Derived* p) : parent_(p) {}
int open() override { return parent_->base2_open(); }
private:
Derived* parent_;
} base2_obj; // Note member object here
int base1_open() { return 111; } /// implement
int base2_open() { return 222; } /// implement
public:
Derived() : base1_obj(this), base2_obj(this) {}
Derived(Derived const&) : base1_obj(this), base2_obj(this) {}
Derived(Derived&&) : base1_obj(this), base2_obj(this) {}
Derived& operator=(Derived const&) { return *this; }
Derived& operator=(Derived&&) { return *this; }
operator Base1&() { return base1_obj; } /// convert to Base1&
operator Base2&() { return base2_obj; } /// convert to Base2&
}; /// class Derived
int base1_open(Base1& b1) { return b1.open(); }
int base2_open(Base2& b2) { return b2.open(); }
int main(void) {
Derived d;
std::cout << base1_open(d) << std::endl; // Like upcasting in inheritance.
std::cout << base2_open(d) << std::endl; // Like upcasting in inheritance.
}
请注意 Derived 类中转换运算符的使用。(Derived 类实际上不是派生类!)转换运算符允许将 Derived 转换为 Base1,即使它们本身没有共享继承关系!使用成员对象 base1_obj 和 base2_obj 消除了对对象生命周期的担忧。成员对象的生命周期与 Derived 对象的生命周期相同。
C++ 编程思想 卷 2 - 实用编程 --- 由 Bruce Eckel 撰写。