• 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

    总结出单继承内存分布大致如下:
    1. 普通继承情况下,先父类元素后子类元素,若父类元素本身也是从某个爷爷类继承而来:父类是虚继承而来,则先父后子再爷爷(其实这个分布是满足规则2的),即爷爷放在最后;父类是普通继承而来,先爷爷后父再子,即爷爷放在前面。
    2. 虚继承情况下,先子类元素后父类元素,如果父类元素本身也是从某个爷爷类继承(不论是虚继承还是普通继承)而来,则父类由类的深到浅依次分布(先爷爷后父,爷爷在子和父之间)。

      多继承的内存分布情况如下:

    1. 虚继承和普通继承同时存在的情况下,先进行普通继承,再进行虚继承。
    2. 继承都是虚继承或者普通继承的时候,按照从左到右声明顺序进行继承,注意,都是虚继承的话,如果继承的相同的类,这个类只会在最先出现的地方出现一次而已;如果是普通继承,相同的类会多次出现。

      总之,先满足基本的父子类分布情况,如果父类还有更深层次的基类,这些基类再依据普通继承和虚继承的情况进行内存分布(即红字标注部分)。另外,具体内存分布情况会不会还与编译环境有关就不得而知了,至少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(){};
    };

     

  • 相关阅读:
    设计模式——创建型设计模式总结(简单工厂、普通工厂、抽象工厂、建造者、原型和单例)
    网易游戏2011招聘笔试题+答案解析
    华为2011上机笔试题2+参考程序
    趋势科技2011校招笔试题+答案解析
    腾讯2012实习生笔试题2+答案解析
    浙商银行2011笔试题+答案解析
    Linux学习笔记(三)——权限管理
    PowerShell在多个文件中检索关键字
    Linux学习笔记(一)——入门
    PowerShell函数调用问题
  • 原文地址:https://www.cnblogs.com/yanqi0124/p/3830433.html
Copyright © 2020-2023  润新知