51Testing软件测试网 g6HA9Src4ig
E.l 二、(虚)继承类的内存占用大小51Testing软件测试网hi3xsy't
C P hw'h)~H&H0 首先,平时所声明的类只是一种类型定义,它本身是没有大小可言的。 因此,如果用sizeof运算符对一个类型名操作,那得到的是具有该类型实体的大小。51Testing软件测试网(L0g {_:M%Q4q:g9M
Pyh8N'r8O]t7q0 计算一个类对象的大小时的规律:
~PXc9oF!`^+k0
51Testing软件测试网| _-k9P,u"j` \O 1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);
.}&~z+ZHL"VoIl0
@5dr;G2U7}O0 2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;
kv/u
st'w C5wp3BJ0
E1o%Y3Z#Xr {Y0 3、因此一个对象的大小≥所有非静态成员大小的总和;
!r8p1D?,P&`~0
51Testing软件测试网5V2FS:W%R,Y:a6k1@ 4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
"a6z!MF&b0
51Testing软件测试网}|6t:oY
V 5、虚承继的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);51Testing软件测试网 h0QF'pT;P$l
*b4e z2ct0 6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;51Testing软件测试网{2O[|x
,OT,H5|gl$u/L0 7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。
U^!G,^U0
51Testing软件测试网C3c2t:?2x6Fi#PB| _4H 示例一:含有普通继承51Testing软件测试网zi/a!c.r
51Testing软件测试网^6tNWu5eu"u:W
51Testing软件测试网%i)n0m4Z
G`;R NJ
51Testing软件测试网*C(P,h
R
m~ofclass A
kpFA;u"p |zk0{
6uWX0U
z'S r;n0}; 51Testing软件测试网b1~'RK
L dX
W
51Testing软件测试网7HxPbA} _class B 51Testing软件测试网 n#X@ `$dy)@!a
{
B?4Gq/v I_
e\#G0 char ch;
,}X.Z1dDQs0 virtual void func0() { }
0z5~;N1uKtAm K0}; 51Testing软件测试网1pd!e{2hr}&w"b%_
6CT'y:s'M:a0class C
n5?|.kML0{
Rt#O `.iqt6g.j0 char ch1;51Testing软件测试网fTj`+U"y-|G
char ch2;
\;rt0n)j3K;jwd(C.T8_0 virtual void func() { }
T!K4~PQse4H
n[0 virtual void func1() { } 51Testing软件测试网T(U-L7Fogm)i
};51Testing软件测试网*KUP?8xWr%E
&S#^ YW6G0class D: public A, public C
dxAr6C7pcg0{ 51Testing软件测试网!Eb!`4{]
int d;
?E9c
@&r0 virtual void func() { }
#Vd \F+w]G/R:Ux6K0 virtual void func1() { }
X{5Z g1I
@q0};
1txX_$G0
{oO5w\4epbP0class E: public B, public C
lc1VVt
~5v,_ zj0{
.Il B_(F f0 int e;
!_)n;}l$E/s;~5tY1f0 virtual void func0() { } 51Testing软件测试网q:x%]0GFO'M
virtual void func1() { }
)qvvb].W {0};51Testing软件测试网)Z:d `!h!K
x&Et
v:i!o0Y&u0int main(void)
-^OJy[%w;fkt0{
4r
bMrR4A:JK
}0 cout<<"A="<<sizeof(A)<<endl; //result=1
+wGLz N0 cout<<"B="<<sizeof(B)<<endl; //result=8 51Testing软件测试网*M*]y\ol-~K
cout<<"C="<<sizeof(C)<<endl; //result=851Testing软件测试网9te*w8f(H \`
cout<<"D="<<sizeof(D)<<endl; //result=1251Testing软件测试网~U!VX{v}Q
cout<<"E="<<sizeof(E)<<endl; //result=2051Testing软件测试网W
{&Nl,h&d&n.WJv
return 0;
+O]w:S7^-V"E.M0}
4|.{3qy'z/?051Testing软件测试网W Q^r1t"v%r 前面三个A、B、C类的内存占用空间大小就不需要解释了,注意一下内存对齐就可以理解了。
H:VN%CS
s/@0
51Testing软件测试网2Q_P1|9Wc _` 求sizeof(D)的时候,需要明白,首先VPTR指向的虚函数表中保存的是类D中的两个虚函数的地址,然后存放基类C中的两个数据成员ch1、ch2,注意内存对齐,然后存放数据成员d,这样4+4+4=12。
+A2J,g6X"K0r-b3k0
51Testing软件测试网LL9z:CO{'E1_%p 求sizeof(E)的时候,首先是类B的虚函数地址,然后类B中的数据成员,再然后是类C的虚函数地址,然后类C中的数据成员,最后是类E中的数据成员e,同样注意内存对齐,这样4+4+4+4+4=20。
n+v}n"?x(V&M0
z9`O#D"[;C"lj.tYU0 示例二:含有虚继承51Testing软件测试网6I~#Pa|7q!C
Y'x8Q+Aa {'u*H:z:uD%]0
51Testing软件测试网V
n,},q3\!]K
51Testing软件测试网+n|M5oN!D4{r"tf class CommonBase t4K!|B3Aj8u0{51Testing软件测试网 Y?[6[:C:{%{9\ int co;51Testing软件测试网lL:|W@6j
FY }; `;k&IaQG^0
t2n-IRt$} G \5w/r0class Base1: virtual public CommonBase51Testing软件测试网-K&t^pK {51Testing软件测试网 [%n}/qRK!A public: 0?Kt4h$m0 virtual void print1() { }51Testing软件测试网(\ Q}Eek D virtual void print2() { } YwCq.j#gU9a0private: ,e.NQ wsj/\ f0 int b1; }Y#n5A _0};51Testing软件测试网7bu Ywc?_%oQ
;z2`E$U1|U'XK8``0class Base2: virtual public CommonBase51Testing软件测试网Fvr4GA v0y"q {51Testing软件测试网"VtZVF public: h5_xjnV,f+Xd0 virtual void dump1() { } 3Z8Q3s0T9L:w8X1qz0 virtual void dump2() { } 4pu]
|?4z.|o0private:51Testing软件测试网HE/vB&pn {y int b2;51Testing软件测试网3Y;P)MK4U[*N5aj5{ }; Hw?3D Vc0
tGn'X#q3J$t8T0class Derived: public Base1, public Base251Testing软件测试网$jM Tizpb`fNf {51Testing软件测试网(o'z{?)H(zl Tg
B0w public:
@jdH)I
XSC0 void print2() { }51Testing软件测试网I]},MMp!X void dump2() { } 1\,q#ez\n
z4So0private:51Testing软件测试网,`Bm2G^X2Rp"q+e int d; Y.Qz?l8D*H(pl#yu0}; F@)q%Yr W0 |
51Testing软件测试网5MIqeB-\ sizeof(Derived)=32,其在内存中分布的情况如下:
WQPm2F}n0
Z+r/v5n5i0e*l0
51Testing软件测试网R.i/@*D,?Fi%ktW
class Derived size(32):51Testing软件测试网w/Et8IM +--- %Z.ZT#r.dT{0 | +--- (base class Base1)51Testing软件测试网J1bX9H.l4l#Ds$x | | {vfptr} S ^rq}1T1V2um"l0 | | {vbptr}51Testing软件测试网dKx~Y'}5}%^9^ | | b151Testing软件测试网
|]z
l8[6OO ZuF | +---51Testing软件测试网&^U [\0J | +--- (base class Base2)51Testing软件测试网z3CR I4z)\ ny6~ | | {vfptr} +C!G F!AGS)n[0 | | {vbptr}51Testing软件测试网-kf,K J
t'H#@#e | | | b2 g.v8Ymx8_0 | +--- oA5~~'{ F0 | d %ZX8P'^c+l0 +---51Testing软件测试网FG7R\a+G
Y$? +--- (virtual base CommonBase)51Testing软件测试网UV
o'E6PANV g8Qe | co51Testing软件测试网
zl7^Z$awJL3V +--- |
51Testing软件测试网.GUY+Ywauq n 示例3:
8p(dy
M"Qu'tR#O;M0
51Testing软件测试网4ak!RY/P
~9F$~/_
51Testing软件测试网4d;Cl{$XSn[9c
51Testing软件测试网
V`rM'x(H)^*~t#IO class A ssJ)}d0{51Testing软件测试网"yB0^9i0dm public: 7DD?8|f
D'c|^@6W
f0 virtual void aa() { } [!g)T-f8|9?J0 virtual void aa2() { }51Testing软件测试网0Wk a\5Z(~`)L private: ?4A,Fx+i0 char ch[3];51Testing软件测试网DAV
x:K}&u }; e8y9D `I)R'{K3]~m0
|-UtTF-q&m8^+T5m0class B: virtual public A51Testing软件测试网7|p e~8U.v(N {51Testing软件测试网 VRM}[Z public:51Testing软件测试网!G DlYSN0T virtual void bb() { }51Testing软件测试网Y8h-CP%c
eXrQ!x virtual void bb2() { }51Testing软件测试网5B7g"U,w~ }; 8b
uhqCr(v,UZ0
P(J:^IFfs0int main(void)51Testing软件测试网3b.J'C9G(X8SbG { &xp
VD6r0 cout<<"A's size is "<<sizeof(A)<<endl;51Testing软件测试网#?'NzfL)a cout<<"B's size is "<<sizeof(B)<<endl; *de8ta-I!W.e;v7\0 return 0;51Testing软件测试网yie
QS9w } +U)t.AS7bUegaw0 |
q3kxA
~0 执行结果:A's size is 851Testing软件测试网%Hp+]P.Ce
f*Ur7v(g0 B's size is 16
_;yC2F+@cw`0
A~TqF0 说明:对于虚继承,类B因为有自己的虚函数,所以它本身有一个虚指针,指向自己的虚表。另外,类B虚继承类A时,首先要通过加入一个虚指针来指向父类A,然后还要包含父类A的所有内容。因此是4+4+8=16。51Testing软件测试网N K8?X2x%bo2G