程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 繼承之虛繼承與普通繼承的內存分布,繼承

C++ 繼承之虛繼承與普通繼承的內存分布,繼承

編輯:C++入門知識

C++ 繼承之虛繼承與普通繼承的內存分布,繼承


C++ 繼承之虛繼承與普通繼承的內存分布


僅供互相學習,請勿噴,有觀點歡迎指出~

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(){};
};

 


C++中虛繼承與一般的繼承有什不同

舉例來說:假如類A和類B是由類X繼承而來(非虛繼承且假設類X包含一些成員),且類C同時繼承了類A和B,那麼C就會擁有兩套和X相關的成員(可分別獨立訪問,一般要用適當的消歧義修飾符)。但是如果類A虛繼承自類X,那麼C將會只包含一組類X的成員數據。

c++虛繼承的內存問題

sizeof(A) + sizeof(B) + sizeof(class_ptr)
class_ptr即類指針,指向virtual說明的虛基類列表
注意,這裡面存在內存對齊規則
第一個代碼:
sizeof(A) + sizeof(B) + sizeof(class_ptr) = 1 + 1 + 4, 對齊,得到8
第二個代碼:
sizeof(A) + sizeof(B) = sizeof(vptr) + sizeof(vptr) = 4 + 4 = 8,虛函數表指針
第三個代碼:
sizeof(A) + sizeof(B) + sizeof(class_ptr) = 4 + 4 + 4 = 12
就是在第二個的基礎上多了一個class_ptr,無論多少個類,都只有一個class_ptr指向這一系列的virtual class。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved