菱形继承是因为C++独有的多重继承的特性,一个子类可以继承自多个父类,这些父类可能继承自其他父类
菱形继承存在浪费存储空间,造成二义性的问题
如何解决:1、虚继承,子类会指向同一个虚表,然后通过虚表的偏移量反向查找父类地址。父类的vptr都有共同的基类偏移量,从而让子类多继承时指向同一个父类的父类。
g++ -fdump-class-hierarchy *.cpp gcc8.0之前
g++ -fdump-lang-class *.cpp gcc8.0之后
class A {
public:
int value;
A() : value(10) {}
};
class B : virtual public A {}; // 虚继承
class C : virtual public A {}; // 虚继承
class D : public B, public C {}; // 继承 A 只有一份
int main() {
D obj;
cout << obj.value << endl; // 不再二义性
return 0;
}
也就是说,在使用虚继承时,编译器会引入虚基类表(VBTable)来存储 A 在最终派生类中的地址偏移量,保证 B
和 C
访问的是同一个 A
。
B 和 C 作为中间类存储了虚基类表(VBTable),其中记录了 A 在最终派生类 D 中的偏移量,而 D 继承了 B 和 C,并且存储了 B 和 C 的地址。