看代码:
class A
{
int a;
virtual void hello(){}
};
class B : virtual public A
{
int a;
virtual void hello(){}
};
class C : virtual public A
{
int a;
virtual void hello(){}
};
class D : public B, public C
{
int a;
virtual void hello(){}
};
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;
}
输出结果是8 16 16 28,看看究竟是怎么来的
首先,类A里面有一个虚函数hello,那么这个类就多了一个隐藏的数据----指向虚函数表(vtbls)的指针(vptrs),我们假设是在32位系统下,所以A的大小为:4+4 = 8;
对于类B,虚继承于A,那么除了类B的成员a和一个vptrs外,还有A的成员a以及vtpr,所以B的大小:4+4+4+4=16;
C与B分析相同。
那么D呢?首先它有自己的成员a以及一个vptrs,再有B、C的成员a和vptrs,同时也存在A的成员a和A的vptrs,由于虚继承的关系D中只保留了A一份副本,这里需要提一下的是,D的vprts是和B或者C的vptrs可以共用,编译器优化,所以D本身的大小是4字节(成员a)
所以D的大小为
4 +4+4 +4+4 +4+4 = 28 byte
D本身 B C A
可以参照下图对象D的内存分配布局:
具体的编译器优化可能有所不同。
另参考 《More Effective C++》第24条款和《深入浅出MFC》第一篇第二章之类与对象大解剖。