浅谈虚继承

一、提出问题。

有以下代码。

class B
{
public:
         int a;
};

class D1 : public B
{
public:
         int b;
};

class D2 : public B
{
public:
         int c;
};

class E :  public D1, public D2
{
public:
         int d;
};

其类图为,

 

B

int a                                                                                             4

D1

B::a , int c                                                                                    8

D2

B::a , int d                                                                                   8

E

D1::B::a , D1::int b , D2::B::a , D2:: int c , int e                          20

 

通过分析内存形态我们发现E中基类B被重复继承了,显然我们不想要这种结果。继续验证一下。

用基类的指针指向子类的对象。

         D1 * pd1 = new D1();
         B * pb = pd1;

  基类指针指向了D1的对象,也就是:D1的对象,是一种B。这样是可以的。

      E pe = new E();

         D1 * pd1 = pe;      //ok 

         D2* pd2 = pe;       //ok

         B* pb = pe;        //error 从E到B转换不明确

二、引入虚继承

以上代码中,我们使用虚继承的方式。

class D1 : virtual public B

class D2 : virtual public B

 

使用类图表示


对于程序员来说,这种类层次图显得更加简单和清晰,不过对于一个编译器来说,这就复杂得多了。

B

int a                                          

4

D1

B::a , int c , vtbl B         

12

D2

B::a , int d , vtbl B                                      

12

E

B::a , D1::int b , D2:: int c , int d,  vtbl D1, vtbl D2          

24

从这里我们看出,子类E每继承一个虚继承的类,都会多使用一个虚表来标记,也就会多占4个字节。

此时我们再验证一下

E* pe = new E();
B* pb = pe;  ///ok

 

虚继承一般会用在菱形的继承结构里面。

posted @ 2012-07-05 14:46  陈朋  阅读(309)  评论(0编辑  收藏  举报