C++菱形继承

来源:互联网 发布:java判断链表是否有环 编辑:程序博客网 时间:2024/06/05 05:01

在c++继承体系中,有一类问题是永远跑不掉的即菱形继承问题。此类问题又被称作钻石继承问题,只是一种较差的设计结构,刚好看到这个问题,特此总结一下。

何为菱形继承

先来看一下菱形继承的基本结构
菱形继承
A和B从基类Base中继承,而D多重继承于A,B。那就意味着D中会有Base中的两个拷贝。因为成员函数不体现在类的内存大小上,所以实际上可以看到的情况是D的内存分布中含有2组Base的成员变量。
又因其结构与钻石有几分相似,又被称作钻石继承。
钻石

代码如下

class Base{public:    Base():a(1){};    void print(){        cout<<a<<endl;    }private:    int a;};class A : public Base{};class B : public Base{};class D:  public A ,  public B{};int main(int argc, char* argv[]){    D d;    cout<<sizeof(d);    d.a=10;//error : 对“a”的访问不明确      d.print();//error : 对“print”的访问不明确  }

输出d的大小为8。若此时示例化D并调用Base中的print成员函数就会出现二义性问题。

虚继承

如何解决钻石继承问题中的二义性问题呢?通过使用虚继承的手段可以保证D只存有基类Base的一份拷贝,虚继承是一种机制,类通过虚继承指出它希望共享虚基类的状态。对给定的虚基类,无论该类在派生层次中作为虚基类出现多少次,只继承一个共享的基类子对象,共享基类子对象称为虚基类。

其省略后的代码如下所示:

class Base {……};class A : virtual public Base{……};class B: virtual public Base{……};class D : public A, public B{ …… };

虚继承和直接继承会有什么区别

  1. 时间:在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚基类对象,只不过这个调整是运行时间接完成的。
  2. 空间:由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝,这样较之多继承节省空间。

最后关于虚继承对象的内存布局 http://blog.csdn.net/BlueDog/article/details/4711169 这篇博文讲的很不错可以作为参考。