避免多重继承自同一非虚基类
5.1.5 ID_diamondInheritance
当派生类有多个基类,这些基类又派生自同一非虚基类时,派生类对象会持有该非虚基类的多个实例,造成逻辑和存储上的冗余。
示例:
struct A {
int i = 0;
};
class B: public A {};
class C: public A {};
class D: public B, public C {}; // Non-compliant
void foo(D& d) {
d.i = 1; // Compile error
d.B::i = 1; // Odd
d.C::i = 1; // Odd
}
在 D 类对象 d 中,基类 A 的成员 i 有两个不同的实例,d 不能直接访问 i,只能通过 d.B::i 或 d.C::i 这种怪异的方式访问。
将共同的基类设为虚基类可以解决这种问题:
class B: virtual public A {};
class C: virtual public A {};
class D: public B, public C {}; // Compliant
void foo(D& d) {
d.i = 1; // OK
}
注意,直接将虚基类指针转为派生类指针会导致标准未定义的行为,如:
void bar(A* a) {
B* p = (B*)a; // Undefined behavior
....
}
这种转换一般不会通过编译,但标准并未要求编译器必须阻止这种转换,改用 dynamic_cast 可解决这些问题:
void bar(A* a) {
B* p = dynamic_cast<B*>(a); // OK
....
}
相关
依据
ISO/IEC 14882:2003 5.2.9(5 8)-undefined
ISO/IEC 14882:2003 10.1(4 5 6)
ISO/IEC 14882:2011 5.2.9(11 12)-undefined
ISO/IEC 14882:2011 10.1(4 5 6 7)