菱形继承
菱形继承也称为钻石型继承或重复继承,它指的是基类被某个派生类简单重复继承了多次。这样,派生类对象中拥有多份基类成员实例,这会占据更多的内存空间,还会引起调用基类成员时的二义性。
代码
class B
{
public:
int ib;
public:
B(int i=1) :ib(i){}
virtual void f() { cout << "B::f()" << endl; }
virtual void Bf() { cout << "B::Bf()" << endl; }
};
class B1 : public B
{
public:
int ib1;
public:
B1(int i = 100 ) :ib1(i) {}
virtual void f() { cout << "B1::f()" << endl; }
virtual void f1() { cout << "B1::f1()" << endl; }
virtual void Bf1() { cout << "B1::Bf1()" << endl; }
};
class B2 : public B
{
public:
int ib2;
public:
B2(int i = 1000) :ib2(i) {}
virtual void f() { cout << "B2::f()" << endl; }
virtual void f2() { cout << "B2::f2()" << endl; }
virtual void Bf2() { cout << "B2::Bf2()" << endl; }
};
class D : public B1, public B2
{
public:
int id;
public:
D(int i= 10000) :id(i){}
virtual void f() { cout << "D::f()" << endl; }
virtual void f1() { cout << "D::f1()" << endl; }
virtual void f2() { cout << "D::f2()" << endl; }
virtual void Df() { cout << "D::Df()" << endl; }
};
继承类图
对象模型
D类对象内存布局中,图中青色表示b1类子对象实例,黄色表示b2类子对象实例,灰色表示D类子对象实例。从图中可以看到,由于D类间接继承了B类两次,导致D类对象中含有两个B类的数据成员ib,一个属于来源B1类,一个来源B2类。这样不仅增大了空间,更重要的是引起了程序歧义:
D d;
d.ib =1 ; //二义性错误,调用的是B1的ib还是B2的ib?
d.B1::ib = 1; //正确
d.B2::ib = 1; //正确
尽管我们可以通过明确指明调用路径以消除二义性,但二义性的潜在性还没有消除,我们可以通过虚继承来使D类只拥有一个ib实体。