C++中的虚继承

#include <iostream>
using namespace std;
class A
{
 virtual void f(){};
};

class B : public virtual  A{

 virtual void f(){};
};

class C: public virtual  A{
 virtual void f(){};
 virtual void t(){};
};

int main() 
{ 
   cout<<sizeof(B)<<endl;
  cout<<sizeof(C)<<endl;
} 

此题在vc6.0下结果是 8 12。

回顾一下虚继承的概念:虚继承主要解决在多重继承中的菱形继承问题,也就是说 B和C类同时继承了A类,然后D类继承了B,C类,那么D类的虚表就会有重复的函数指针,虚继承就不会了……。实现方法是,在子类中保存一个父类(虚继承类)的实体,同时保存一个指针指向这个实体。指针+实体都是属于子类,所以sizeof会将两者也算在内。

cout<<sizeof(B)<<endl; 结果是8原因是 sizeof(A)加上 指向A实体的指针。注意此时没有属于B的虚指针。也就是说B没有自己的虚函数。

cout<<sizeof(C)<<endl; C B区别在于C中有一个属于自己的虚函数,所以加上了一个虚指针的大小 所有为12

有了之前的那个思想,我来讲解下 各个结构体的 sizeof();

代码如下:

struct A

{

    A(int v=100):X(v){};

    virtual void foo(void){}

    int X;

};

A:很简单 一个虚表指针 +一个 X 一共是8byte

struct B :virtual public A

{

    B(int v=10):Y(v),A(100){};

    virtual void fooB(void){}

    int Y;

};

B:虚继承,OK 那就是 sizeof(A)+一个指向虚基类的指针4byte+判断B中的虚函数是不是从A继承的,如果是则这一部分是0,如果不是则还要再加4byte 存放 虚表 那么 B一共就是20byte。

struct C : virtual public A

{

    C(int v=20):Z(v),A(100){}

    virtual void fooC(void){}

    int Z;

};

C的分析同A

struct D : public B, public C

{

    D(int v =40):B(10),C(20),A(100),L(v){}

    virtual void fooD(void){}

    int L;

};

D:公共继承B,C,那么 直接 sizeof(b)+sizeof(C)+自己的一个虚指针-因为B,C都是虚继承A,那么B和C中关于A的指针只要保存一个,所以要减去4个字节,那么D最后一共就是40byte OK

int _tmain(int argc, _TCHAR* argv[])

{



    A a;

    int *ptr;

    ptr = (int*)&a;

    cout << ptr << " sizeof = " << sizeof(a) <<endl;

    for(int i=0;i<sizeof(A)/sizeof(int);i++)

    {

        if(ptr[i] < 10000)

        {

             cout << dec << ptr[i]<<endl;

        }

        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;

    }



    cout << "--------------------------------------" <<endl;



    B b;

    ptr = (int*)&b;

    cout <<"addr:" << ptr << " sizeof = " << sizeof(b) <<endl;

    for(int i=0;i<sizeof(B)/sizeof(int);i++)

    {

        if(ptr[i] < 10000)

        {

             cout << dec << ptr[i]<<endl;

        }

        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;

    }



    cout << "--------------------------------------" <<endl;



    D d;

    ptr = (int*)&d;

    cout <<"addr:" << ptr << " sizeof = " << sizeof(d) <<endl;

    for(int i=0;i<sizeof(D)/sizeof(int);i++)

    {

        if(ptr[i] < 10000)

        {

             cout << dec << ptr[i]<<endl;

        }

        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;

    }

    return 0;

}

最后一段话很重要:那就是 各个编译器运行的关于虚继承的结果不一样,很简单,他们处理虚表的机制不一样,但是有一点可以肯定的是,虚继承就是为了解决菱形继承中,B,C都继承了A,D继承了B,C,那么D关于 A的引用只有一次,而不是 普通继承的 对于A引用了两次……

所以上面分析的都是浮云 没用的东西。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值