1 菱形继承
从图中,我们知道派生类D继承B,C,所以D中存在B,C的所有数据,而由于B,C也都继承A,所以D中有两份A的数据,m_a,所以D无法直接访问A中的数据,必须加限定作用域指明是来自于哪个基类B,C中的m_a。
class Base
{
public:
int m_base;
};
class A : public Base
{
public:
int m_a;
};
class B :public Base
{
public:
int m_b;
};
class D : public A, public B
{
public:
int m_d;
};
void main()
{
D d;
d.m_d = 0;
//d.m_a = 1; 不能访问
d.m_b = 2;
d.m_base=3;
//d.A::m_base = 3;//要访问只有加限定作用域
//d.B::m_base = 4;
}
2 解决办法
而如果A,B是虚拟继承(使得在派生类中只保留一份间接基类的成员。),则能防止B中有两份base的数据。如果是虚拟继承,则只有一份base的数据,存在D中,而A,B则存放虚基表(里面存放对base的偏移量)
代码
class Base
{
public:
int m_base;
};
class A : virtual public Base
{
public:
int m_a;
};
class B :virtual public Base
{
public:
int m_b;
};
class D : public A, public B
{
public:
int m_d;
};
void main()
{
D d;
d.m_d = 0;
d.m_a = 1;
d.m_b = 2;
d.m_base=3;
//d.A::m_base = 3;//如果是非虚拟继承,加限定作用域
//d.B::m_base = 4;
}
虚拟继承,对于D的两个基类,A,B各自产生一份虚基表
输入虚基表的地址
偏移量为14 00 00 00 即为20,在内存一上A开始向后20位,为m_base的位置
如果不是虚拟继承
同上,可以看出A存放的m_base=3,B的m_base=4,造成二义性和冗余