针对于GCC,VC6.0 编译器 对虚继承内存大小的探讨 以如下代码分析:
#include <iostream>
using namespace std;
class A {
int a;
char b;
public:
virtual ~A(){}
};
class B:virtual public A{
public:
virtual ~B(){}
virtual void B1(){}
};
class C:virtual public A{
public:
virtual ~C(){}
virtual void C1(){}
};
class D:public B,public C{
public:
virtual ~D(){}
virtual void D1(){}
};
int main()
{
cout<<"sizeof(A)="<<sizeof(A)<<endl;
cout<<"sizeof(B)="<<sizeof(B)<<endl;
cout<<"sizeof(C)="<<sizeof(C)<<endl;
cout<<"sizeof(D)="<<sizeof(D)<<endl;
return 0;
}
运行结果 如下:
分析:
GCC环境下:
A中int+char+虚表指针(内存看齐)。B,C中由于是虚继承因此大小为A+指向虚基类的指针(大小为4),B,C虽然加入了自己的虚函数,但是在gcc编译器中虚表指针是和基类共享的,因此不会有自己的虚表指针。D由于B,C都是虚继承,因此D只包含一个A的副本,结果D大小就等同于A+B中的指向虚基类的指针+C中的指向虚基类的指针。
如果B,C不是虚继承,而是普通继承的话,那么A,B,C的大小都是12(没有指向虚基类的指针了),而D由于不是虚继承,因此包含两个A副本,大小为24. 注意此时虽然D的大小和虚继承一样,但是内存布局却不同。
针对于普通继承,以上代码测试结果如下:
VC6.0环境下:
但是在VC6.0下面 虚表指针和基类是不共享的,因此每个类还需要单独自己的虚表指针。B,C由于继承A因此大小为A+指向虚基类的指针+指向自己虚表的指针即(20)。D继承了B,C,而B,C同时继承了A,因此只含有一个A的副本即可。结果D的大小就等同于A+B指针基类指针+C指向虚基类的指针+D本身指向虚基类的指针+A的虚表指针( 12+4+4+4+4 = 28).
代码测试结果如图: