僅供互相學習,請勿噴,有觀點歡迎指出~
class A
{
virtual void aa(){};
};
class B : public virtual A
{
char j[3]; //加入一個變量是為了看清楚class中的vfptr放在什麼位置
public:
virtual void bb(){};
};
class C : public virtual A
{
char i[3];
public:
virtual void cc(){};
};
class C1 : public A
{
char i1[3];
public:
virtual void cc1(){};
};
class D : public C
{
char d[3];
public:
virtual void dd(){};
};
class D1 : public C1
{
char d1[3];
public:
virtual void dd1(){};
};
class E : public virtual C
{
char e[3];
public:
virtual void ee(){};
};
class E1 : public virtual C1
{
char e1[3];
public:
virtual void ee1(){};
};
class F : public C, public virtual B
{
char f[3];
public:
virtual void ff(){};
};
class F1 : public virtual C, public B
{
char f1[3];
public:
virtual void ff1(){};
};
class G : public virtual E
{
char g[3];
public:
virtual void gg(){};
};
class H : public virtual E, public virtual C
{
char h[3];
public:
virtual void hh(){};
};
class H1 : public E, public C1
{
char h1[3];
public:
virtual void hh1(){};
};
在VS2013下,在項目->屬性->C/C++->命令行中添加/d1reportAllClassLayout即可查看所有類的內存分布情況:
1> class A size(4):
1> +---
1> 0 | {vfptr}
1> +---
1>
1> A::$vftable@:
1> | &A_meta
1> | 0
1> 0 | &A::aa
1>
1> A::aa this adjustor: 0
1>
1>
1> class B size(16):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | j
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 12 | {vfptr}
1> +---
1>
1> B::$vftable@B@:
1> | &B_meta
1> | 0
1> 0 | &B::bb
1>
1> B::$vbtable@:
1> 0 | -4
1> 1 | 8 (Bd(B+4)A)
1>
1> B::$vftable@A@:
1> | -12
1> 0 | &A::aa
1>
1> B::bb this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 12 4 4 0
1>
1>
1> class C size(16):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | i
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 12 | {vfptr}
1> +---
1>
1> C::$vftable@C@:
1> | &C_meta
1> | 0
1> 0 | &C::cc
1>
1> C::$vbtable@:
1> 0 | -4
1> 1 | 8 (Cd(C+4)A)
1>
1> C::$vftable@A@:
1> | -12
1> 0 | &A::aa
1>
1> C::cc this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 12 4 4 0
1>
1>
1> class C1 size(8):
1> +---
1> | +--- (base class A)
1> 0 | | {vfptr}
1> | +---
1> 4 | i1
1> | <alignment member> (size=1)
1> +---
1>
1> C1::$vftable@:
1> | &C1_meta
1> | 0
1> 0 | &A::aa
1> 1 | &C1::cc1
1>
1> C1::cc1 this adjustor: 0
1>
1>
1> class D size(20):
1> +---
1> | +--- (base class C)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | i
1> | | <alignment member> (size=1)
1> | +---
1> 12 | d
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 16 | {vfptr}
1> +---
1>
1> D::$vftable@C@:
1> | &D_meta
1> | 0
1> 0 | &C::cc
1> 1 | &D::dd
1>
1> D::$vbtable@:
1> 0 | -4
1> 1 | 12 (Dd(C+4)A)
1>
1> D::$vftable@A@:
1> | -16
1> 0 | &A::aa
1>
1> D::dd this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 16 4 4 0
1>
1>
1> class D1 size(12):
1> +---
1> | +--- (base class C1)
1> | | +--- (base class A)
1> 0 | | | {vfptr}
1> | | +---
1> 4 | | i1
1> | | <alignment member> (size=1)
1> | +---
1> 8 | d1
1> | <alignment member> (size=1)
1> +---
1>
1> D1::$vftable@:
1> | &D1_meta
1> | 0
1> 0 | &A::aa
1> 1 | &C1::cc1
1> 2 | &D1::dd1
1>
1> D1::dd1 this adjustor: 0
1>
1>
1> class E size(28):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | e
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 12 | {vfptr}
1> +---
1> +--- (virtual base C)
1> 16 | {vfptr}
1> 20 | {vbptr}
1> 24 | i
1> | <alignment member> (size=1)
1> +---
1>
1> E::$vftable@:
1> | &E_meta
1> | 0
1> 0 | &E::ee
1>
1> E::$vbtable@E@:
1> 0 | -4
1> 1 | 8 (Ed(E+4)A)
1> 2 | 12 (Ed(E+4)C)
1>
1> E::$vftable@A@:
1> | -12
1> 0 | &A::aa
1>
1> E::$vftable@C@:
1> | -16
1> 0 | &C::cc
1>
1> E::$vbtable@C@:
1> 0 | -4
1> 1 | -8 (Ed(C+4)A)
1>
1> E::ee this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 12 4 4 0
1> C 16 4 8 0
1>
1>
1> class E1 size(20):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | e1
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base C1)
1> | +--- (base class A)
1> 12 | | {vfptr}
1> | +---
1> 16 | i1
1> | <alignment member> (size=1)
1> +---
1>
1> E1::$vftable@E1@:
1> | &E1_meta
1> | 0
1> 0 | &E1::ee1
1>
1> E1::$vbtable@:
1> 0 | -4
1> 1 | 8 (E1d(E1+4)C1)
1>
1> E1::$vftable@C1@:
1> | -12
1> 0 | &A::aa
1> 1 | &C1::cc1
1>
1> E1::ee1 this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> C1 12 4 4 0
1>
1>
1> class F size(32):
1> +---
1> | +--- (base class C)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | i
1> | | <alignment member> (size=1)
1> | +---
1> 12 | f
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 16 | {vfptr}
1> +---
1> +--- (virtual base B)
1> 20 | {vfptr}
1> 24 | {vbptr}
1> 28 | j
1> | <alignment member> (size=1)
1> +---
1>
1> F::$vftable@C@:
1> | &F_meta
1> | 0
1> 0 | &C::cc
1> 1 | &F::ff
1>
1> F::$vbtable@C@:
1> 0 | -4
1> 1 | 12 (Fd(C+4)A)
1> 2 | 16 (Fd(F+4)B)
1>
1> F::$vftable@A@:
1> | -16
1> 0 | &A::aa
1>
1> F::$vftable@B@:
1> | -20
1> 0 | &B::bb
1>
1> F::$vbtable@B@:
1> 0 | -4
1> 1 | -8 (Fd(B+4)A)
1>
1> F::ff this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 16 4 4 0
1> B 20 4 8 0
1>
1>
1> class F1 size(32):
1> +---
1> | +--- (base class B)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | j
1> | | <alignment member> (size=1)
1> | +---
1> 12 | f1
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 16 | {vfptr}
1> +---
1> +--- (virtual base C)
1> 20 | {vfptr}
1> 24 | {vbptr}
1> 28 | i
1> | <alignment member> (size=1)
1> +---
1>
1> F1::$vftable@B@:
1> | &F1_meta
1> | 0
1> 0 | &B::bb
1> 1 | &F1::ff1
1>
1> F1::$vbtable@B@:
1> 0 | -4
1> 1 | 12 (F1d(B+4)A)
1> 2 | 16 (F1d(F1+4)C)
1>
1> F1::$vftable@A@:
1> | -16
1> 0 | &A::aa
1>
1> F1::$vftable@C@:
1> | -20
1> 0 | &C::cc
1>
1> F1::$vbtable@C@:
1> 0 | -4
1> 1 | -8 (F1d(C+4)A)
1>
1> F1::ff1 this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 16 4 4 0
1> C 20 4 8 0
1>
1>
1> class G size(40):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | g
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 12 | {vfptr}
1> +---
1> +--- (virtual base C)
1> 16 | {vfptr}
1> 20 | {vbptr}
1> 24 | i
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base E)
1> 28 | {vfptr}
1> 32 | {vbptr}
1> 36 | e
1> | <alignment member> (size=1)
1> +---
1>
1> G::$vftable@G@:
1> | &G_meta
1> | 0
1> 0 | &G::gg
1>
1> G::$vbtable@:
1> 0 | -4
1> 1 | 8 (Gd(G+4)A)
1> 2 | 12 (Gd(G+4)C)
1> 3 | 24 (Gd(G+4)E)
1>
1> G::$vftable@A@:
1> | -12
1> 0 | &A::aa
1>
1> G::$vftable@C@:
1> | -16
1> 0 | &C::cc
1>
1> G::$vbtable@C@:
1> 0 | -4
1> 1 | -8 (Gd(C+4)A)
1>
1> G::$vftable@E@:
1> | -28
1> 0 | &E::ee
1>
1> G::$vbtable@E@:
1> 0 | -4
1> 1 | -20 (Gd(E+4)A)
1> 2 | -16 (Gd(E+4)C)
1>
1> G::gg this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 12 4 4 0
1> C 16 4 8 0
1> E 28 4 12 0
1>
1>
1> class H size(40):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | h
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 12 | {vfptr}
1> +---
1> +--- (virtual base C)
1> 16 | {vfptr}
1> 20 | {vbptr}
1> 24 | i
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base E)
1> 28 | {vfptr}
1> 32 | {vbptr}
1> 36 | e
1> | <alignment member> (size=1)
1> +---
1>
1> H::$vftable@H@:
1> | &H_meta
1> | 0
1> 0 | &H::hh
1>
1> H::$vbtable@:
1> 0 | -4
1> 1 | 8 (Hd(H+4)A)
1> 2 | 12 (Hd(H+4)C)
1> 3 | 24 (Hd(H+4)E)
1>
1> H::$vftable@A@:
1> | -12
1> 0 | &A::aa
1>
1> H::$vftable@C@:
1> | -16
1> 0 | &C::cc
1>
1> H::$vbtable@C@:
1> 0 | -4
1> 1 | -8 (Hd(C+4)A)
1>
1> H::$vftable@E@:
1> | -28
1> 0 | &E::ee
1>
1> H::$vbtable@E@:
1> 0 | -4
1> 1 | -20 (Hd(E+4)A)
1> 2 | -16 (Hd(E+4)C)
1>
1> H::hh this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 12 4 4 0
1> C 16 4 8 0
1> E 28 4 12 0
1>
1>
1> class H1 size(40):
1> +---
1> | +--- (base class E)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | e
1> | | <alignment member> (size=1)
1> | +---
1> | +--- (base class C1)
1> | | +--- (base class A)
1> 12 | | | {vfptr}
1> | | +---
1> 16 | | i1
1> | | <alignment member> (size=1)
1> | +---
1> 20 | h1
1> | <alignment member> (size=1)
1> +---
1> +--- (virtual base A)
1> 24 | {vfptr}
1> +---
1> +--- (virtual base C)
1> 28 | {vfptr}
1> 32 | {vbptr}
1> 36 | i
1> | <alignment member> (size=1)
1> +---
1>
1> H1::$vftable@E@:
1> | &H1_meta
1> | 0
1> 0 | &E::ee
1> 1 | &H1::hh1
1>
1> H1::$vftable@C1@:
1> | -12
1> 0 | &A::aa
1> 1 | &C1::cc1
1>
1> H1::$vbtable@E@:
1> 0 | -4
1> 1 | 20 (H1d(E+4)A)
1> 2 | 24 (H1d(E+4)C)
1>
1> H1::$vftable@A@:
1> | -24
1> 0 | &A::aa
1>
1> H1::$vftable@C@:
1> | -28
1> 0 | &C::cc
1>
1> H1::$vbtable@C@:
1> 0 | -4
1> 1 | -8 (H1d(C+4)A)
1>
1> H1::hh1 this adjustor: 0
1>
1> vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 24 4 4 0
1> C 28 4 8 0
總結出單繼承內存分布大致如下:
多繼承的內存分布情況如下:
總之,先滿足基本的父子類分布情況,如果父類還有更深層次的基類,這些基類再依據普通繼承和虛繼承的情況進行內存分布(即紅字標注部分)。另外,具體內存分布情況會不會還與編譯環境有關就不得而知了,至少sizeof類的大小是會與編譯環境有關的(http://www.cnblogs.com/yanqi0124/p/3829964.html文章最後對比了gcc和VC下sizeof的不同,因為對虛表指針的處理方式不同)
根據上述解釋,就能解釋程序員面試寶典中的一題:
class A
{
virtual aa(){};
};
class B : public virtual A
{
char j[3]; //加入一個變量是為了看清楚class中的vfptr放在什麼位置
public:
virtual bb(){};
};
class C : public virtual B
{
char i[3];
public:
virtual cc(){};
};
