C++中虚函数工作原理和(虚)继承类的内存占用大小计算-2
上一篇 / 下一篇 2012-08-21 09:26:30 / 个人分类:C++
二、(虚)继承类的内存占用大小
? \7i6e Ia r9W%]]0_!am6`sF%@qv0 首先,平时所声明的类只是一种类型定义,它本身是没有大小可言的。 因此,如果用sizeof运算符对一个类型名操作,那得到的是具有该类型实体的大小。51Testing软件测试网_?1\b9n|q
51Testing软件测试网+s1e9qPszm计算一个类对象的大小时的规律:51Testing软件测试网r+e%b"^T2X8sw?
,NR;Fuvy;?? Rb0 1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);
zF/v$ZW-r0 51Testing软件测试网){&h&s8M0m2z7ia2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;
5d!e3O G5Zh9b09wH6e6Cy(s0 3、因此一个对象的大小≥所有非静态成员大小的总和;
,hMv-r^beL0 51Testing软件测试网-iz)l1V3S RF)[-c;P6m4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
&GnMjXqaf`0-f J~3Anc-M)Tz`0 5、虚承继的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);
c8} eB {%h2TrY"O0 51Testing软件测试网*o9Grr yV(dzM+u6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;51Testing软件测试网z4V`t6n9pJI
Oqq#Y#at0 7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。51Testing软件测试网P-b#|4\vY"[~
Qs[tXct0 示例一:含有普通继承51Testing软件测试网#[7X.t,R w^ a%H;`b
4^2~ qW4D9]3k0
h+[iwV2b%wO+N0$z5DeS Z$A\z:\5d#K0class A
!h!Q6Lg8@3O&R^0{
RPB,~f{v~0}; 51Testing软件测试网3Bfg*gT{%[A\t
(D5}FI G6Z(i0class B
'e1eX}cX0{51Testing软件测试网
J0c!k lt!{7P&]
char ch;
4f6h#h0Xs1A0dn-\l0 virtual void func0() { }
{7S!i6M1D3\N'?\0};
bXLTLYT0class C
6lvxp*F-w`@0{
P9BDj6Ao`0 char ch1;51Testing软件测试网0?$^'U5kI
char ch2;
yE#y!eH`B%rjvs0 virtual void func() { } 51Testing软件测试网&\Ms,J,K
H
virtual void func1() { }
1Y+Ao6A2qi;mh3a+O)O#f0};
class D: public A, public C
5SH1h"Vf3E0{ 51Testing软件测试网9@5r;S,M'k$LW:d1f `(Y
int d; 51Testing软件测试网%m}/XGj
Bf/@B(y
virtual void func() { } 51Testing软件测试网0Q0CACK/tV2{
virtual void func1() { }51Testing软件测试网0pYvSE'Ck2J \
};
,G I+H1fB0class E: public B, public C
O-Z&Zgs$o0{
h5[BR g'j9c0 int e;
)pO+s'm y
jL0 virtual void func0() { } 51Testing软件测试网*F/w
S?C;u8P.iJ7t
s
virtual void func1() { }
h(ap BZ3k0};
F8z.|4M+l#d o c%L!|5P{0int main(void)
!j'e&I9PI4L be
Z/^M1l0{51Testing软件测试网)b-cqYBu,?6Ln
cout<<"A="<<sizeof(A)<<endl; //result=1
M#L"vXD.l%M0 cout<<"B="<<sizeof(B)<<endl; //result=8
)j-rF%p6FsH
@ Z0 cout<<"C="<<sizeof(C)<<endl; //result=8
pCE0P'e\]f0 cout<<"D="<<sizeof(D)<<endl; //result=1251Testing软件测试网"ob/K.|[)oYC
cout<<"E="<<sizeof(E)<<endl; //result=2051Testing软件测试网 \'z?,do]+D2{
return 0;
S,L-C9W2H^0}51Testing软件测试网t'c.vt9H-W{{
前面三个A、B、C类的内存占用空间大小就不需要解释了,注意一下内存对齐就可以理解了。51Testing软件测试网'mibJ a2i E
51Testing软件测试网8zdO?5H8I求sizeof(D)的时候,需要明白,首先VPTR指向的虚函数表中保存的是类D中的两个虚函数的地址,然后存放基类C中的两个数据成员ch1、ch2,注意内存对齐,然后存放数据成员d,这样4+4+4=12。51Testing软件测试网9Ly U!gT&T"e/e
] L'JFdZl'b0 求sizeof(E)的时候,首先是类B的虚函数地址,然后类B中的数据成员,再然后是类C的虚函数地址,然后类C中的数据成员,最后是类E中的数据成员e,同样注意内存对齐,这样4+4+4+4+4=20。
F\S7GO M[7D/G0.HXVQ n0 示例二:含有虚继承
@M~^*^?:D]0 51Testing软件测试网*lT}.Nq)h5_s'er)JN:N3gD0
{}p/vo&O_V ]:l_ _0class CommonBase51Testing软件测试网*jN9S8Y;E#KK 7q&UcyBO)C gR0class Base1: virtual public CommonBase Xh'p
RpLtE0class Base2: virtual public CommonBase51Testing软件测试网
{)j4_LQlc4J3^-O |