此题在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引用了两次……
所以上面分析的都是浮云 没用的东西。