多个类继承了同一个公共基类,而这些派生类又同时被一个类继承,这种称为菱形继承或钻石继承。
多个类继承了同一个公共基类,而这些派生类又同时被一个类继承,这种称为菱形继承或钻石继承
B和C同时继承了A的成员,此时D继承B和C,相当于获得了两份A的成员,造成数据冗余。
B和C同时继承了A中的a,然后又派生出了D,因而D中存在两份a:一份是B::a,一份是C::a。因此,在D中直接访问a会导致错误,此时的a就具有二义性,需要指定类作用域才能访问。
虚拟继承的意义在于:解决菱形继承中数据冗余和二义性的问题。
class A{
public:
int a;
};
class B :virtual public A{
public:
int b;
};
class C :virtual public A{
public:
int c;
};
class D :public B, public C{
int d;
};
此时D从B、C继承来B::a和C::a的a就是唯一的一份,可以直接通过D::a访问。这里的A被称为虚基类。
B、C中原本重复的数据变成了虚基类表指针,该指针指向了一个虚基类表,虚基类表中存储了该指针到公共数据所在内存的偏移量。
注:公共数据的位置可能是D的开头,也可能是结尾,依编译器而定
简单来说:
注:虚基类表的第一项是该指针与自身的偏移量,即0。第二项是该指针与公共数据的偏移量。