body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}

VS 调试查看内存布局:

(选中项目右键——》调试——》属性——》C/C++——》命令行——》其他——》/d1reportSingleClassLayoutB(最后一个B代表代码中的B类)——》解决方案资源管理器选中右键重新生成
(结合源码进行测试)  
// 测试一:单个虚继承,不带虚函数
//    虚继承与继承的区别
//       1.多了一个虚基指针
//       2.虚基类位于派生类存储空间的最末尾
// 测试二:单个虚继承,带虚函数
//   1.如果派生类没有自己的虚函数,此时派生类对象不会产生
//    虚函数指针,有和基类一样的虚函数也不会产生虚函数指针
//   2.如果派生类拥有自己的虚函数,此时派生类对象就会产生自己本身的虚函数指针,
//     并且该虚函数指针位于派生类对象存储空间的开始位置

//单个继承,不带虚函数
1>  class A        size(4):
1>          +---
1>   0        | _ia
1>          +---
1>  class B        size(8):
1>          +---  //如果B类自己有虚函数,和下同
1>          | +--- (base class A)
1>   0        | | _ia
1>          | +---
1>   4        | _ib
class A
{
public:
        A() : _ia(10){}
        void f()
        {        cout << "A::f()" << endl;        }
private:
        int _ia;
};
class B :   public A
{
public:
        B() : _ib(20){}
        void f()
        {        cout << "B::f()" << endl;        }

        void fb()
        {        cout << "B::fb()" << endl;        }  
         void fb2()
        {        cout << "B::fb2()" << endl;        }
private:
        int _ib;
};
//单个继承,带虚函数
1>  class A        size(8):
1>          +---
1>   0        | {vfptr}   //虚函数指针->虚函数表
1>   4        | _ia
1>          +---
1>  class B        size(12):
1>          +---
1>          | +--- (base class A)
1>   0        | | {vfptr}   (A中的虚函数被覆盖)
1>   4        | | _ia
1>          | +---
1>   8        | _ib
1>          +---
class A
{
public:
        A() : _ia(10){}
       virtual  void f()
        {        cout << "A::f()" << endl;        }
private:
        int _ia;
};
class B :   public A
{
public:
        B() : _ib(20){}
       virtual void f()
        {        cout << "B::f()" << endl;        }
        virtual void fb2()

        {        cout << "B::fb2()" << endl;        }
        void fb()
        {        cout << "B::fb()" << endl;      }   
private:
        int _ib;
};
1>  A::$vftable@:
1>          | &A_meta
1>          |  0
1>   0        | &A::f
1>  B::$vftable@:
1>          | &B_meta
1>          |  0
1>   0        | &B::f
1>   1        | &B::fb2
// 类B没有虚函数
1>  class B        size(12):
1>          +---
1>          | +--- (base class A)
1>   0        | | {vfptr}
1>   4        | | _ia
1>          | +---
1>   8        | _ib
1>          +---
1>  B::$vftable@:
1>          | &B_meta
1>          |  0
1>   0        | &A::f
1>  class A        size(8):
1>          +---
1>   0        | {vfptr}
1>   4        | _ia
1>          +---
1>  class B        size(24):
1>          +---
1>   0        | {vfptr}   //这里只会存自己类独有的虚函数
1>   4        | {vbptr}   //虚基指针->虚基表
1>   8        | _ib
1>          +---
1>  12        | (vtordisp for vbase A)
1>          +--- (virtual base A)
1>  16        | {vfptr} //A中的f被覆盖,存放的是B的f()
1>  20        | _ia

//类A同上;B没有 virtual void fb2()和f()
1>  class B        size(16):
1>          +---
1>   0        | {vbptr}
1>   4        | _ib
1>          +---
1>          +--- (virtual base A)
1>   8         | {vfptr}
1>  12        | _ia
1>          +---

class B :  virtual  public A
{
public:
       B() : _ib(20){}
        virtual void f()
        {        cout << "B::f()" << endl;        }

        void fb()
        {        cout << "B::fb()" << endl;        }
        virtual void fb2()
        {        cout << "B::fb2()" << endl;        }
private:
        int _ib;
};
1>  A::$vftable@:
1>          | &A_meta
1>          |  0
1>   0        | &A::f
1>  B::$vftable@B@:
1>          | &B_meta
1>          |  0
1>   0        | &B::fb2
1> 
1>  B::$vbtable@:
1>   0        | -4
1>   1        | 12 (Bd(B+4)A)
1> 
1>  B::$vftable@A@:
1>             | -16
1>   0        | &(vtordisp) B::f
1> 
1>  B::f this adjustor: 16
1>  B::f2 this adjustor: 0

1>  B::$vbtable@:
1>   0        | 0
1>   1        | 8 (Bd(B+0)A)
1> 
1>  B::$vftable@:
1>            | -8
1>   0        | &A::f

正常单个继承内存布局基类在前;基类有虚函数最开头有虚函数指针;继承过来可能产生覆盖。虚继承,基类在内存布局的后面,布局开头是虚基指针,如果派生类有自己独有的虚函数,那么还会有一个虚函数指针,指向存放自己独有的虚函数的表,下面的基类会多一个4字节字段存放vtordisp,并且基类中和派生类重复的虚函数会被覆盖。
正常多个继承,和单一一样,每个基类的虚函数指针都继承过来,如果有产生覆盖(派生类和多个基类中都有同样的虚函数),则第一个基函数表存放覆盖的函数地址,和派生类特有的虚函数,后面的基类布局如果有和第一个基类一样的虚函数且产生覆盖,只会存放偏移量指向第一个基类覆盖的虚函数地址
//类A同上;B没有 virtual void fb2()

1>  class B        size(20):
1>          +---
1>   0        | {vbptr}
1>   4        | _ib
1>          +---
1>  8        | (vtordisp for vbase A)
1>          +--- (virtual base A)
1>  12        | {vfptr}
1>  16        | _ia
1>          +---
1>  B::$vbtable@:
1>  0        | 0
1>  1        | 12 (Bd(B+0)A)
1>
1>  B::$vftable@:
1>          | -12
1>  0        | &(vtordisp) B::f
1>
1>  B::f this adjustor: 12
vtordisp for vbase A: 虚继承中派生类重写了基类的虚函数,并且在构造函数或者析构函数中使用指向基类的指针调用了该函数,编译器会为虚基类添加vtordisp域。

上述示例代码便会产生vtordisp字段!条件是。
1. 派生类重写了虚基类的虚函数。
2. 派生类定义了构造函数或者析构函数。
它所解决的问题是:由于对类的虚拟基的置换与对其派生类的置换之间有差异,可能会向虚函数传递错误的 this 指针。 该解决方案向类的各个虚拟基提供称作 vtordisp 字段的单个构造置换调整。
预编译命令关闭vtordisp字段的产生。
*只有在你确信所有类的构造函数或析构函数都虚拟地调用了虚拟函数,vtordisp才可以关掉。

#pragma vtordisp({on|off})

// 测试三:多重继承(带虚函数)        
// 1. 每个基类都有自己的虚函数表
//   2. 派生类如果有自己的虚函数,会被加入到第一个虚函数表之中
//   3.   内存布局中, 其基类的布局按照基类被声明时的顺序进行排列
// 4. 派生类会覆盖基类的虚函数,只有第一个虚函数表中存放的是真实的被覆盖的函数的地址;其它的虚函数表中存放的并不是真实的对应的虚函数的地址,而只是一条跳转指令
class Base1
{
public:
        Base1() : _iBase1(10){}
        virtual void f()
        {        cout << "Base1::f()" << endl;        }
        virtual void g()
        {        cout << "Base1::g()" << endl;        }
        virtual void h()
        {        cout << "Base1::h()" << endl;        }
private:
        int _iBase1;
};
class Base2
{
public:
        Base2() : _iBase2(100){}
        virtual void f()
        {    cout << "Base2::f()" << endl;    }
        virtual void g()
        {    cout << "Base2::g()" << endl;   }
        virtual void h()
        {    cout << "Base2::h()" << endl;   }
private:
        int _iBase2;
};
class Base3
{
public:
        Base3() : _iBase3(1000){}
        virtual void f()
        {     cout << "Base3::f()" << endl;   }
        virtual void g()
        {     cout << "Base3::g()" << endl;   }
        virtual void h()
        {     cout << "Base3::h()" << endl;   }
private:
        int _iBase3;
};
class Derived 
:public Base1,public Base2,public Base3
{
public:
        Derived() : _iDerived(10000){}
        void f()
        {        cout << "Derived::f()" << endl;        }
        virtual void g1()   // 会放到Base1的虚函数表
        {        cout << "Derived::g1()" << endl;        }
private:
        int _iDerived;       
};
1>  class Base1        size(8):
1>          +---
1>   0        | {vfptr}
1>   4        | _iBase1
1>          +---

1>  class Base2        size(8):
1>          +---
1>   0        | {vfptr}
1>   4        | _iBase2
1>          +---

1>  class Base3        size(8):
1>          +---
1>   0        | {vfptr}
1>   4        | _iBase3
1>          +---

1>  class Derived        size(28):
1>          +---
1>          | +--- (base class Base1)
1>   0        | | {vfptr}
1>   4        | | _iBase1
1>          | +---
1>          | +--- (base class Base2)
1>   8        | | {vfptr}
1>  12        | | _iBase2
1>          | +---
1>          | +--- (base class Base3)
1>  16        | | {vfptr}
1>  20        | | _iBase3
1>          | +---
1>  24        | _iDerived
1>          +---
1>  Base1::$vftable@:
1>          | &Base1_meta
1>          |  0
1>  0        | &Base1::f
1>  1        | &Base1::g
1>  2        | &Base1::h
1> 
1>  Base1::f this adjustor: 0
1>  Base1::g this adjustor: 0
1>  Base1::h this adjustor: 0

1>  Base2::$vftable@:
1>          | &Base2_meta
1>          |  0
1>  0        | &Base2::f
1>  1        | &Base2::g
1>  2        | &Base2::h
1> 
1>  Base2::f this adjustor: 0
1>  Base2::g this adjustor: 0
1>  Base2::h this adjustor: 0

1>  Base3::$vftable@:
1>          | &Base3_meta
1>          |  0
1>  0        | &Base3::f
1>  1        | &Base3::g
1>  2        | &Base3::h
1> 
1>  Base3::f this adjustor: 0
1>  Base3::g this adjustor: 0
1>  Base3::h this adjustor: 0

1>  Derived::$vftable@Base1@:
1>          | &Derived_meta
1>          |  0
1>   0        | &Derived::f
1>   1        | &Base1::g
1>   2        | &Base1::h
1>   3        | &Derived::g1
1> 
1>  Derived::$vftable@Base2@:
1>          | -8
1>   0        | &thunk: this-=8; goto Derived::f
1>   1        | &Base2::g
1>   2        | &Base2::h
1> 
1>  Derived::$vftable@Base3@:
1>          | -16
1>   0        | &thunk: this-=16; goto Derived::f
1>   1        | &Base3::g
1>   2        | &Base3::h
1> 
1>  Derived::f this adjustor: 0
1>  Derived::g1 this adjustor: 0

难点
class Derived
:virtual public Base1, 
virtual  public Base2,
virtual  public Base3
{
public:
        Derived() : _iDerived(10000){}
        void f()
        {        cout << "Derived::f()" << endl;        }
        virtual void g1() 
        {        cout << "Derived::g1()" << endl;        }
private:
        int _iDerived;      
};
1>  class Derived        size(48):
1>          +---
1>  0        | {vfptr}  //存放g1()
1>  4        | {vbptr}
1>  8        | _iDerived
1>          +---
1>  12        | (vtordisp for vbase Base1)
1>          +--- (virtual base Base1)
1>  16        | {vfptr}
1>  20        | _iBase1
1>          +---
1>  24        | (vtordisp for vbase Base2)
1>          +--- (virtual base Base2)
1>  28        | {vfptr}
1>  32        | _iBase2
1>          +---
1>  36        | (vtordisp for vbase Base3)
1>          +--- (virtual base Base3)
1>  40        | {vfptr}
1>  44        | _iBase3
1>          +---
class Derived
:virtual public Base1,
virtual  public Base2,
virtual  public Base3

{
public:
        Derived() : _iDerived(10000){}
        void f()
        {        cout << "Derived::f()" << endl;        }
        /*virtual*/ void g1() 
        {        cout << "Derived::g1()" << endl;        }
private:
        int _iDerived;      
};

1>  class Derived        size(44):
1>          +---
1>   0        | {vbptr}
1>   4        | _iDerived
1>          +---
1>  8         | (vtordisp for vbase Base1)
1>          +--- (virtual base Base1)
1>  12        | {vfptr}
1>  16        | _iBase1
1>          +---
1>  20        | (vtordisp for vbase Base2)
1>          +--- (virtual base Base2)
1>  24        | {vfptr}
1>  28        | _iBase2
1>          +---
1>  32        | (vtordisp for vbase Base3)
1>          +--- (virtual base Base3)
1>  36        | {vfptr}
1>  40        | _iBase3
1>          +---
1>  Derived::$vftable@Derived@:
1>          | &Derived_meta
1>          |  0
1>   0     | &Derived::g1
1> 
1>  Derived::$vbtable@:
1>   0        | -4
1>   1        | 12 (Derivedd(Derived+4)Base1)
1>   2        | 24 (Derivedd(Derived+4)Base2)
1>   3        | 36 (Derivedd(Derived+4)Base3)
1> 
1>  Derived::$vftable@Base1@:
1>          | -16
1>   0        | &(vtordisp) Derived::f
1>   1        | &Base1::g
1>   2        | &Base1::h
1> 
1>  Derived::$vftable@Base2@:
1>          | -28
1>   0        | &(vtordisp) thunk: this-=12; goto Derived::f
1>   1        | &Base2::g
1>   2        | &Base2::h
1> 
1>  Derived::$vftable@Base3@:
1>          | -40
1>   0        | &(vtordisp) thunk: this-=24; goto Derived::f
1>   1        | &Base3::g
1>   2        | &Base3::h
1>  Derived::$vbtable@:
1>   0        | 0
1>   1        | 12 (Derivedd(Derived+0)Base1)
1>   2        | 24 (Derivedd(Derived+0)Base2)
1>   3        | 36 (Derivedd(Derived+0)Base3)
1> 
1>  Derived::$vftable@Base1@:
1>          | -12
1>   0        | &(vtordisp) Derived::f
1>   1        | &Base1::g
1>   2        | &Base1::h
1> 
1>  Derived::$vftable@Base2@:
1>          | -24
1>   0        | &(vtordisp) thunk: this-=12; goto Derived::f
1>   1        | &Base2::g
1>   2        | &Base2::h
1> 
1>  Derived::$vftable@Base3@:
1>          | -36
1>   0        | &(vtordisp) thunk: this-=24; goto Derived::f
1>   1        | &Base3::g
1>   2        | &Base3::h

1>  class Derived        size(28):
1>          +---
1>          | +--- (base class Base1)
1>   0        | | {vfptr}
1>   4        | | _iBase1
1>          | +---
1>          | +--- (base class Base2)
1>   8        | | {vfptr}
1>  12        | | _iBase2
1>          | +---
1>          | +--- (base class Base3)
1>  16        | | {vfptr}
1>  20        | | _iBase3
1>          | +---
1>  24        | _iDerived
1>          +---
1>  Derived::$vftable@Base1@:
1>          | &Derived_meta
1>          |  0
1>   0        | &Derived::f
1>   1        | &Base1::g
1>   2        | &Base1::h
1>   3        | &Derived::g1
1>  Derived::$vftable@Base2@:
1>          | -8
1>   0        | &thunk: this-=8; goto Derived::f
1>   1        | &Base2::g
1>   2        | &Base2::h 
1>  Derived::$vftable@Base3@:
1>          | -16
1>   0        | &thunk: this-=16; goto Derived::f
1>   1        | &Base3::g
1>   2        | &Base3::h 
B1:  4+4 =8
B2:  4+4 =8
B3:  4+4 =8
D:B1,B2,B3:   8+8+8+4=28
// 测试四:

虚基类没有采用虚继承
class B
{
public:
        B() : _ib(10), _cb('B'){}
        virtual void f()
        {        cout << "B::f()" << endl;        }
        virtual void Bf()
        {        cout << "B::Bf()" << endl;        }
private:
        int _ib;
        char _cb;
};
class B1 : public B
{
public:
        B1() : _ib1(100), _cb1('1'){}
        virtual void f()
        {     cout << "B1::f()" << endl;     }       
        virtual void f1()
        {     cout << "B1::f1()" << endl;       }
        virtual void Bf1()
        {     cout << "B1::Bf()" << endl;        }
private:
        int _ib1;
        char _cb1;
};
class B2 : public B
{
public:
        B2() : _ib2(1000), _cb2('2'){}
        virtual void f()
        {   cout << "B2::f()" << endl;   }
        virtual void f2()
        {   cout << "B2::f2()" << endl;   }
        virtual void Bf2()
        {   cout << "B2::Bf2()" << endl;  }
private:
        int _ib2;
        char _cb2;
};
class D : public B1, public B2
{
public:
        D() : _id(10000), _cd('3'){}
        virtual void f()
        {    cout << "D::f()" << endl;   }
        virtual void f1()
        {    cout << "D::f1()" << endl;  }
        virtual void f2()
        {     cout << "D::f2()" << endl;  }
        virtual void Df()
        {     cout << "D::Df()" << endl;  }
private:
        int _id;
        char _cd;
};
重点
1>  class B        size(12):
1>          +---
1>   0        | {vfptr}
1>   4        | _ib
1>   8        | _cb
1>            | <alignment member> (size=3)  
//这里表示内存对齐数量
1>          +---
1>  B::$vftable@:
1>          | &B_meta
1>          |  0
1>   0        | &B::f
1>   1        | &B::Bf
1> 
1>  B::f this adjustor: 0
1>  B::Bf this adjustor: 0

1>  class B1        size(20):
1>          +---
1>          | +--- (base class B)
1>   0        | | {vfptr}
1>   4        | | _ib
1>   8        | | _cb
1>            | | <alignment member> (size=3)
1>          | +---
1>  12        | _ib1
1>  16        | _cb1
1>            | <alignment member> (size=3)
1>          +---

1>  B1::$vftable@:
1>          | &B1_meta
1>          |  0
1>   0        | &B1::f
1>   1        | &B::Bf
1>   2        | &B1::f1
1>   3        | &B1::Bf1
1> 
1>  B1::f this adjustor: 0
1>  B1::f1 this adjustor: 0
1>  B1::Bf1 this adjustor: 0

1>  class B2        size(20):
1>          +---
1>          | +--- (base class B)
1>   0        | | {vfptr}
1>   4        | | _ib
1>   8        | | _cb
1>            | | <alignment member> (size=3)
1>          | +---
1>  12        | _ib2
1>  16        | _cb2
1>            | <alignment member> (size=3)
1>          +---
1>  B2::$vftable@:
1>          | &B2_meta
1>          |  0
1>   0        | &B2::f
1>   1        | &B::Bf
1>   2        | &B2::f2
1>   3        | &B2::Bf2
1> 
1>  B2::f this adjustor: 0
1>  B2::f2 this adjustor: 0
1>  B2::Bf2 this adjustor: 0

1>  class D        size(48):
1>          +---
1>          | +--- (base class B1)
1>          | | +--- (base class B)
1>   0        | | | {vfptr}
1>   4        | | | _ib
1>   8        | | | _cb
1>            | | | <alignment member> (size=3)
1>          | | +---
1>  12        | | _ib1
1>  16        | | _cb1
1>            | | <alignment member> (size=3)
1>          | +---
1>          | +--- (base class B2)
1>          | | +--- (base class B)
1>  20        | | | {vfptr}
1>  24        | | | _ib
1>  28        | | | _cb
1>            | | | <alignment member> (size=3)
1>          | | +---
1>  32        | | _ib2
1>  36        | | _cb2
1>            | | <alignment member> (size=3)
1>          | +---
1>  40        | _id
1>  44        | _cd
1>            | <alignment member> (size=3)
1>          +---
1>  D::$vftable@B1@:
1>          | &D_meta
1>          |  0
1>  0        | &D::f
1>  1        | &B::Bf
1>  2        | &D::f1
1>  3        | &B1::Bf1
1>  4        | &D::Df
1>  D::$vftable@B2@:
1>          | -20
1>  0        | &thunk: this-=20; goto D::f
1>  1        | &B::Bf
1>  2        | &D::f2
1>  3        | &B2::Bf2
1> 
1>  D::f this adjustor: 0
1>  D::f1 this adjustor: 0
1>  D::f2 this adjustor: 20
1>  D::Df this adjustor: 0

1>  class D        size(48):
1>          +---
1>          | +--- (base class B1)
1>          | | +--- (base class B)
1>   0        | | | {vfptr}
1>   4        | | | _ib
1>   8        | | | _cb
1>            | | | <alignment member> (size=3)
1>          | | +---
1>  12        | | _ib1
1>  16        | | _cb1
1>            | | <alignment member> (size=3)
1>          | +---
1>          | +--- (base class B2)
1>          | | +--- (base class B)
1>  20        | | | {vfptr}
1>  24        | | | _ib
1>  28        | | | _cb
1>            | | | <alignment member> (size=3)
1>          | | +---
1>  32        | | _ib2
1>  36        | | _cb2
1>            | | <alignment member> (size=3)
1>          | +---
1>  40        | _id
1>  44        | _cd
1>            | <alignment member> (size=3)
1>          +---
B:    4+4+1 =9 --->12
B1:B:  4+4+1 + 4+1 =14--->16
B2:B:  4+4+1 + 4+1 =14--->16
D:B1,B2:    12+16+16+4+1 =45--->48
//采用虚继承

//虚基指针所指向的虚基表的内容:
//1. 虚基指针的第一条内容表示的是该虚基指针距离所在的子对象的首地址的偏移
//2. 虚基指针的第二条内容表示的是该虚基指针距离虚基类子对象的首地址的偏移
class B
{
public:
        B() : _ib(10), _cb('B'){}
        virtual void f()
        {        cout << "B::f()" << endl;        }
        virtual void Bf()
        {        cout << "B::Bf()" << endl;        }
private:
        int _ib;
        char _cb;
};
class B1 : virtual public B
{
public:
        B1() : _ib1(100), _cb1('1'){}
        virtual void f()
        {     cout << "B1::f()" << endl;     }       
        virtual void f1()
        {     cout << "B1::f1()" << endl;   }
        virtual void Bf1()
        {     cout << "B1::Bf1()" << endl;   }
private:
        int _ib1;
        char _cb1;
};
class B2 : virtual public B
{
public:
        B2() : _ib2(1000), _cb2('2'){}
        virtual void f()
        {    cout << "B2::f()" << endl;     }
        virtual void f2()
        {    cout << "B2::f2()" << endl;    }
        virtual void Bf2()
        {    cout << "B2::Bf2()" << endl;  }
private:
        int _ib2;
        char _cb2;
};
class D : public B1, public B2
{
public:
        D() : _id(10000), _cd('3'){}
        virtual void f()
        {    cout << "D::f()" << endl;  }
        virtual void f1()
        {    cout << "D::f1()" << endl;  }
        virtual void f2()
        {     cout << "D::f2()" << endl;  }
        virtual void Df()
        {     cout << "D::Df()" << endl;   }
private:
        int _id;
        char _cd;
};
1>  class B        size(12):
1>          +---
1>   0        | {vfptr}
1>   4        | _ib
1>   8        | _cb
1>            | <alignment member> (size=3)
1>          +---
1> 
1>  B::$vftable@:
1>          | &B_meta
1>          |  0
1>   0        | &B::f
1>   1        | &B::Bf
1> 
1>  B::f this adjustor: 0
1>  B::Bf this adjustor: 0

1>  class B1        size(32):
1>          +---
1>   0        | {vfptr}
1>   4        | {vbptr}
1>   8        | _ib1
1>  12        | _cb1
1>            | <alignment member> (size=3)
1>          +---
1>  16        | (vtordisp for vbase B)
1>          +--- (virtual base B)
1>  20        | {vfptr}
1>  24        | _ib
1>  28        | _cb
1>            | <alignment member> (size=3)
1>          +---
1> 
1>  B1::$vftable@B1@:
1>          | &B1_meta
1>          |  0
1>   0        | &B1::f1
1>   1        | &B1::Bf1
1> 
1>  B1::$vbtable@:
1>   0        | -4
1>   1        | 16 (B1d(B1+4)B)
1> 
1>  B1::$vftable@B@:
1>          | -20
1>   0        | &(vtordisp) B1::f
1>   1        | &B::Bf
1> 
1>  B1::f this adjustor: 20
1>  B1::f1 this adjustor: 0
1>  B1::Bf1 this adjustor: 0

1>  class B2        size(32):
1>          +---
1>   0        | {vfptr}
1>   4        | {vbptr}
1>   8        | _ib2
1>  12        | _cb2
1>            | <alignment member> (size=3)
1>          +---
1>  16        | (vtordisp for vbase B)
1>          +--- (virtual base B)
1>  20        | {vfptr}
1>  24        | _ib
1>  28        | _cb
1>            | <alignment member> (size=3)
1>          +---
1> 
1>  B2::$vftable@B2@:
1>          | &B2_meta
1>          |  0
1>   0        | &B2::f2
1>   1        | &B2::Bf2
1> 
1>  B2::$vbtable@:
1>   0        | -4
1>   1        | 16 (B2d(B2+4)B)
1> 
1>  B2::$vftable@B@:
1>          | -20
1>   0        | &(vtordisp) B2::f
1>   1        | &B::Bf
1> 
1>  B2::f this adjustor: 20
1>  B2::f2 this adjustor: 0
1>  B2::Bf2 this adjustor: 0

1>  class D        size(56):
1>          +---
1>          | +--- (base class B1)
1>   0        | | {vfptr}
1>   4        | | {vbptr}
1>   8        | | _ib1
1>  12        | | _cb1
1>            | | <alignment member> (size=3)
1>          | +---
1>          | +--- (base class B2)
1>  16        | | {vfptr}
1>  20        | | {vbptr}
1>  24        | | _ib2
1>  28        | | _cb2
1>            | | <alignment member> (size=3)
1>          | +---
1>  32        | _id
1>  36        | _cd
1>            | <alignment member> (size=3)
1>          +---
1>  40        | (vtordisp for vbase B)
1>          +--- (virtual base B)
1>  44        | {vfptr}
1>  48        | _ib
1>  52        | _cb
1>            | <alignment member> (size=3)
1>          +---
1> 
1>  D::$vftable@B1@:
1>          | &D_meta
1>          |  0
1>   0        | &D::f1
1>   1        | &B1::Bf1
1>   2        | &D::Df
1> 
1>  D::$vftable@B2@:
1>          | -16
1>   0        | &D::f2
1>   1        | &B2::Bf2
1> 
1>  D::$vbtable@B1@:
1>   0        | -4
1>   1        | 40 (Dd(B1+4)B)
1> 
1>  D::$vbtable@B2@:
1>   0        | -4
1>   1        | 24 (Dd(B2+4)B)
1> 
1>  D::$vftable@B@:
1>          | -44
1>   0        | &(vtordisp) D::f
1>   1        | &B::Bf
1> 
1>  D::f this adjustor: 44
1>  D::f1 this adjustor: 0
1>  D::f2 this adjustor: 16
1>  D::Df this adjustor: 0

1>  class D        size(52):
1>          +---
1>          | +--- (base class B1)
1>   0        | | {vfptr}
1>   4        | | {vbptr}
1>   8        | | _ib1
1>  12        | | _cb1
1>            | | <alignment member> (size=3)
1>          | +---
1>          | +--- (base class B2)
1>  16        | | {vfptr}
1>  20        | | {vbptr}
1>  24        | | _ib2
1>  28        | | _cb2
1>            | | <alignment member> (size=3)
1>          | +---
1>  32        | _id
1>  36        | _cd
1>            | <alignment member> (size=3)
1>          +---
1>          +--- (virtual base B)
1>  40        | {vfptr}
1>  44        | _ib
1>  48        | _cb
1>            | <alignment member> (size=3)
1>          +---
B : 4+1+4 =9      4+4+1=9--->12
B1:v B  : 4+1+4+4+4+4+1 =22          4+4+4+1=13--->16
B2:v B  : 4+1+4+4+4+4+1 =22          4+4+4+1=13--->16
D:B1,B2 :    12+16+16=44  +4+1 =49--->13*4=52

1>  D::$vftable@B1@:
1>          | &D_meta
1>          |  0
1>   0        | &D::f1
1>   1        | &B1::Bf1
1>   2        | &D::Df
1>  D::$vftable@B2@:
1>          | -16
1>   0        | &D::f2
1>   1        | &B2::Bf2
1> 
1>  D::$vbtable@B1@:
1>   0        | -4
1>   1        | 36 (Dd(B1+4)B)
1>  D::$vbtable@B2@:
1>   0        | -4
1>   1        | 20 (Dd(B2+4)B)
[原理最清晰]
        http://blog.csdn.net/jinri1234/article/details/5702011

        http://blog.csdn.net/haoel/article/details/3081328

        http://blog.csdn.net/haoel/article/details/3081385


        [虚函数表里边保存的不一定是虚函数的地址]
        http://www.cnblogs.com/cswuyg/archive/2010/08/20/1804716.html

        [C++对象内存布局测试总结]
        http://www.cnblogs.com/cswuyg/archive/2010/08/20/1804113.html

        [布局最清晰]
        http://blog.csdn.net/wangqiulin123456/article/details/8074891

C++各种类继承关系的内存布局的更多相关文章

  1. 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局

    继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...

  2. c++继承中的内存布局

    今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化    译 译者前言 一个C ...

  3. 从汇编看c++的虚拟继承以及其内存布局(一)

    先看第一种最简单的情形,所有类中没有任何虚函数的菱形继承. 下面是c++源码: class Top {//虚基类 public: int i; Top(int ii) { i = ii; } }; c ...

  4. C++对象模型:单继承,多继承,虚继承,菱形虚继承,及其内存布局图

    C++目前使用的对象模型: 此模型下,nonstatic数据成员被置于每一个类的对象中,而static数据成员则被置于类对象之外,static和nonstatic函数也都放在类对象之外(通过函数指针指 ...

  5. 继承关系在内存和DB中的映射

    使用 将若干相似的类映射为单表,对拥有许多特殊数据的类使用具体表继承. 对高层次使用类表继承,对低层次使用具体表继承. Single Table Inheritance 在DB中将类继承层次设计为一个 ...

  6. C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布

    1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...

  7. 转: c++继承中的内存布局

    英文原文: http://www.openrce.org/articles/files/jangrayhood.pdf 翻译: http://blog.csdn.net/jiangyi711/arti ...

  8. 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。

    本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...

  9. 虚继承之单继承的内存布局(VC在编译时会把vfptr放到类的头部,这和Delphi完全一致)

    C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内 ...

随机推荐

  1. eclipse中怎么调出左边项目列表,解决方法:主界面的最上面一栏的Window--ShowView--Project Explorer

    主界面的最上面一栏的Window--ShowView--Project Explorer

  2. DirectX之顶点法线的计算

    首先要明白,顶点法线存在的原因:确定灯光照射到物体表面的角度.所以一提到顶点法线,肯定要进行与灯光相关的运算了. 下面是顶点法线的计算方式 假如 A.B.C三个顶点构成一个三角形,它们对应的顶点法线分 ...

  3. Java中类似C#中Task.wait()的类CountDownLatch

    当主线程开辟多个子线程,而又需要这些子线程都执行完成后再执行主线程后续的操作,在C#中可以通过Task的wait方法来实现,然而在Java中也有类型的类CountDownLatch,具体用法如下: p ...

  4. 自定义WPF控件(MyTextBox、MyDatePicker、MyDataGrid)

    方案一:样式与代码结合 按照UserControl的前后台结合的方式编写MyControl,前台写样式,后台写功能.规则等(创建一个UserControl,然后修改一下即可) 方案二:样式与代码分离 ...

  5. OSPF - 1,基础

    1,OSPF知识点a)在OSPF中,如果是环回口宣告进OSPF,不管宣告时配置的是多少位掩码,路由器收到的都是32位.(EIGRP配了多少位就收到多少位).好处:EIGRP中,在PING包发起时如果在 ...

  6. CSS之透视perspective属性

    透视原理: 近大远小 . 浏览器透视:把近大远小的所有图像,透视在屏幕上. 书写方式不同的定义 perspective有两种定义方式,如下 .class{ perspective: 800px; } ...

  7. 利用phpqrcode二维码生成类库和imagecopymerge函数制拼接图片的经验

    前期准备 引入phpqrcode类库(下载地址:https://sourceforge.net/projects/phpqrcode/) PHP开启GD扩展库支持 1.利用phpqrcode生成二维码 ...

  8. Vasya And The Mushrooms CodeForces - 1016C (前缀和模拟)

    大意: 给定2*n的矩阵, 每个格子有权值, 走到一个格子的贡献为之前走的步数*权值, 每个格子只能走一次, 求走完所有格子最大贡献. 沙茶模拟打了一个小时总算打出来了 #include <io ...

  9. 【转】XP系统远程桌面连接2012R2提示:远程计算机需要网络级别身份验证,而您的计算机不支持该验证

    一.背景 因对方客户的服务器是内网的,需要操作更新服务器的数据库表信息,因此远程对方客户办公司的电脑远程服务器:但是在远程桌面连接出现问题. 二.错误问题 错误问题:“远程计算机需要网络级别身份验证, ...

  10. 『TensorFlow』分布式训练_其三_多机分布式

    本节中的代码大量使用『TensorFlow』分布式训练_其一_逻辑梳理中介绍的概念,是成熟的多机分布式训练样例 一.基本概念 Cluster.Job.task概念:三者可以简单的看成是层次关系,tas ...