#include<iostream>
using
namespace
std;
class
A
{
};
class
B
{
char
ch;
virtual
void
func0() { }
};
class
C
{
char
ch1;
char
ch2;
virtual
void
func() { }
virtual
void
func1() { }
};
class
D:
public
A,
public
C
{
int
d;
virtual
void
func() { }
virtual
void
func1() { }
};
class
E:
public
B,
public
C
{
int
e;
virtual
void
func0() { }
virtual
void
func1() { }
};
int
main(
void
)
{
cout<<
"A="
<<
sizeof
(A)<<endl;
//result=1
cout<<
"B="
<<
sizeof
(B)<<endl;
//result=16
cout<<
"C="
<<
sizeof
(C)<<endl;
//result=16
cout<<
"D="
<<
sizeof
(D)<<endl;
//result=16
cout<<
"E="
<<
sizeof
(E)<<endl;
//result=32
return
0;
}
在GCC编译器下进行编译,有如下结果
结果分析:
1.A为空类,所以大小为1 ;
2.B的大小为char数据成员大小+vptr指针大小。由于字节对齐,大小为8+8=16 ;
3.C的大小为两个char数据成员大小+vptr指针大小。由于字节对齐,大小为8+8=16 ;
4.D为多继承派生类,由于D有数据成员,所以继承空类A时,空类A的大小1字节并没有计入当中,D继承C,此情况D只需要一个vptr指针,所以大小为数据成员加一个指针大小。由于字节对齐,大小为8+8=16 ;
5.E为多继承派生类,此情况为我们上面所讲的多重继承,含虚函数覆盖的情况。此时大小计算为数据成员的大小+2个基类虚函数表指针大小 ,考虑字节对齐,继承顺序B在先,B(8 + 1),然后是C(8+1+1),由于字节对齐,B得与C中最大值对齐,因此B+7变成16,再+C(10),得26,最后+E的其它成员+1,因为要整体对于最大值(8)对齐,因此补齐得32。
在vc编译器下进行编译,有如下结果
结果分析:
4.D为多继承派生类,由于D有数据成员,所以继承空类A时,空类A的大小1字节并没有计入当中,D继承C,此情况D只需要一个vptr指针,所以大小为数据成员加一个指针大小。这里和GCC最大的区别就是D和C不能合并在一起单独进行内存对齐的计算,需要分开进行计算,所以由于字节对齐,大小为8+1+1+6+4+4=24 ;
5.E为多继承派生类,含虚函数覆盖的情况。此时大小计算为数据成员的大小+2个基类虚函数表指针大小 ,同样犹豫每个类需要单独进行内存对齐的计算,所以有8+1+7+8+1+1+6+4+4=40
二.虚继承的情况
对虚继承层次的对象的内存布局,在不同编译器实现有所区别。
在这里,首先要说的是在gcc编译器下,虚继承大小的计算。它在gcc下实现比较简单,不管是否虚继承,GCC都是将虚表指针在整个继承关系中共享的,不共享的是指向虚基类的指针。
class
A {
int
a;
virtual
void
myfuncA(){}
};
class
B:
virtual
public
A{
virtual
void
myfunB(){}
};
class
C:
virtual
public
A{
virtual
void
myfunC(){}
};
class
D:
public
B,
public
C{
virtual
void
myfunD(){}
};
sizeof(A)=16,sizeof(B)=24,sizeof(C)=24,sizeof(D)=48;
A的大小为int大小加上虚表指针大小;
B,C中由于是虚继承,因此大小为int大小加指向虚基类的指针的大小。B,C虽然加入了自己的虚函数,但是虚表指针是和基类共享的,因此不会有自己的虚表指针,他们两个共用虚基类A的虚表指针。D由于B,C都是虚继承,其大小等于B+C)。
在VC编译器下,有如下结果图:
在VC编译器下,由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大小为:16(或16乘以多继承时父类的个数),vc下虚表指针不会共享;
sizeof(C)=32,其中内存分布如下图所示:
- class C size(32):
- +---
- | | {vfptr}
- | | {vbptr}
- | | {vptr}
- | +---
- | +--- (virtual base class A)
- | a
sizeof(D)=48,其中内存分布如下图所示:
- class D size(48):
- +---
- | +--- (base class B)
- | | {vfptr}
- | | {vbptr}
- | +---
- | +--- (base class C)
- | | {vfptr}
- | | {vbptr}
- | +---
- | |{vptr}
- +---
- +--- (virtual base A)
- | d
- +---