C++各种类继承关系的内存布局

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::[email protected]:

1>          | &A_meta

1>          |  0

1>   0        | &A::f


1>  B::[email protected]:

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::[email protected]:

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::[email protected]:

1>          | &A_meta

1>          |  0

1>   0        | &A::f


1>  B::[email protected]@:

1>          | &B_meta

1>          |  0

1>   0        | &B::fb2

1>

1>  B::[email protected]:

1>   0        | -4

1>   1        | 12 (Bd(B+4)A)

1>

1>  B::[email protected]@:

1>             | -16

1>   0        | &(vtordisp) B::f

1>

1>  B::f this adjustor: 16

1>  B::f2 this adjustor: 0

1>  B::[email protected]:

1>   0        | 0

1>   1        | 8 (Bd(B+0)A)

1>

1>  B::[email protected]:

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::[email protected]:

1>  0        | 0

1>  1        | 12 (Bd(B+0)A)

1>

1>  B::[email protected]:

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::[email protected]:

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::[email protected]:

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::[email protected]:

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::[email protected]@:

1>          | &Derived_meta

1>          |  0

1>   0        | &Derived::f

1>   1        | &Base1::g

1>   2        | &Base1::h

1>   3        | &Derived::g1

1>

1>  Derived::[email protected]@:

1>          | -8

1>   0        | &thunk: this-=8; goto Derived::f

1>   1        | &Base2::g

1>   2        | &Base2::h

1>

1>  Derived::[email protected]@:

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::[email protected]@:

1>          | &Derived_meta

1>          |  0

1>   0     | &Derived::g1

1>

1>  Derived::[email protected]:

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::[email protected]@:

1>          | -16

1>   0        | &(vtordisp) Derived::f

1>   1        | &Base1::g

1>   2        | &Base1::h

1>

1>  Derived::[email protected]@:

1>          | -28

1>   0        | &(vtordisp) thunk: this-=12; goto Derived::f

1>   1        | &Base2::g

1>   2        | &Base2::h

1>

1>  Derived::[email protected]@:

1>          | -40

1>   0        | &(vtordisp) thunk: this-=24; goto Derived::f

1>   1        | &Base3::g

1>   2        | &Base3::h


1>  Derived::[email protected]:

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::[email protected]@:

1>          | -12

1>   0        | &(vtordisp) Derived::f

1>   1        | &Base1::g

1>   2        | &Base1::h

1>

1>  Derived::[email protected]@:

1>          | -24

1>   0        | &(vtordisp) thunk: this-=12; goto Derived::f

1>   1        | &Base2::g

1>   2        | &Base2::h

1>

1>  Derived::[email protected]@:

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::[email protected]@:

1>          | &Derived_meta

1>          |  0

1>   0        | &Derived::f

1>   1        | &Base1::g

1>   2        | &Base1::h

1>   3        | &Derived::g1

1>  Derived::[email protected]@:

1>          | -8

1>   0        | &thunk: this-=8; goto Derived::f

1>   1        | &Base2::g

1>   2        | &Base2::h

1>  Derived::[email protected]@:

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::[email protected]:

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::[email protected]:

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::[email protected]:

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::[email protected]@:

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::[email protected]@:

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::[email protected]:

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::[email protected]@:

1>          | &B1_meta

1>          |  0

1>   0        | &B1::f1

1>   1        | &B1::Bf1

1>

1>  B1::[email protected]:

1>   0        | -4

1>   1        | 16 (B1d(B1+4)B)

1>

1>  B1::[email protected]@:

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::[email protected]@:

1>          | &B2_meta

1>          |  0

1>   0        | &B2::f2

1>   1        | &B2::Bf2

1>

1>  B2::[email protected]:

1>   0        | -4

1>   1        | 16 (B2d(B2+4)B)

1>

1>  B2::[email protected]@:

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::[email protected]@:

1>          | &D_meta

1>          |  0

1>   0        | &D::f1

1>   1        | &B1::Bf1

1>   2        | &D::Df

1>

1>  D::[email protected]@:

1>          | -16

1>   0        | &D::f2

1>   1        | &B2::Bf2

1>

1>  D::[email protected]@:

1>   0        | -4

1>   1        | 40 (Dd(B1+4)B)

1>

1>  D::[email protected]@:

1>   0        | -4

1>   1        | 24 (Dd(B2+4)B)

1>

1>  D::[email protected]@:

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::[email protected]@:

1>          | &D_meta

1>          |  0

1>   0        | &D::f1

1>   1        | &B1::Bf1

1>   2        | &D::Df

1>  D::[email protected]@:

1>          | -16

1>   0        | &D::f2

1>   1        | &B2::Bf2

1>

1>  D::[email protected]@:

1>   0        | -4

1>   1        | 36 (Dd(B1+4)B)

1>  D::[email protected]@:

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

原文地址:https://www.cnblogs.com/meihao1203/p/9368296.html

时间: 2024-10-12 07:21:55

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

【转】c++继承中的内存布局

今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化    译 译者前言 一个C++程序员,想要进一步提升技术水平的话,应该多了解一些语言的语意细节.对于使用VC++的程序员来说,还应该了解一些VC++对于C++的诠释. Inside the C++ Object Model虽然是一本好书,然而,书的篇幅多一些,又和具体的VC++关系小一些.因此,从篇幅和内容来看,译者认为本文

C++虚拟继承 类的内存布局

1. 单个虚拟继承 只是为了分析而已,实际中并没有太大的作用.跟虚拟继承相关的派生类对象的内存布局跟具体的编译器相关. (1)VS编译器:无论有无虚函数,必然含有虚基类表指针.虚基类表中的内容为本类实例的偏移和基类实例的相对偏移值.如果有虚函数,那么基类的虚函数表跟派生类的虚函数表是分开的. 在内存布局上,地址从低到高,顺序如下:派生类的虚函数表指针+虚基类表指针+派生类的成员变量+"间隔"(4个字节)+基类的虚函数表指针+基类的成员变量.派生类跟基类实例的位置关系跟普通继承正好相反.

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

使用 将若干相似的类映射为单表,对拥有许多特殊数据的类使用具体表继承. 对高层次使用类表继承,对低层次使用具体表继承. Single Table Inheritance 在DB中将类继承层次设计为一个单表,表中各列代表不同类中的所有域. 运行机制 每个类负责把与之相关的数据保存在表的一行中.表中其它不相关的列留空. 通过表中的Type字段来决定向内存中加载对象时,应该实例化那个类来创建该对象. 可以直接使用类名称 或者需要经过翻译的Code域. 保存数据的代码可以由层超类负责. 使用时机 优点

虚继承中的内存布局

直接看例子就好: #include "qdatetime.h" class Person { public: Person(QString name, QDate birthdate) QObject(name.ascii()), m_Birthdate(birthdate) {} Person(const Person& p) : QObject(p), m_Birthdate(p.m_Birthdate) {} private: QDate m_Birthdate; };

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

C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内存空间中又是如何布局的,却可以对C++的了解深入不少.这段时间花了一些时间了解这些玩意,搞得偶都,不过总算有些收获,嘿嘿. 先看一段代码class A{      virtual aa(){};}; class B : public virtual  A{      char j[3];      

C++对象内存布局 (二)

在上一篇文章中讨论了C++单一一般继承的对象内存布局http://www.cnblogs.com/uangyy/p/4621561.html 接下来继续讨论第二种情况: 2.单一的虚拟继承:有成员变量,有虚函数和虚函数的覆盖,虚拟继承. 我们假设下面这样一种继承关系 源码如下: #include <iostream> using namespace std; class Parent { public: int iparent; Parent() : iparent(10) {} virtua

多重继承和虚继承的内存布局

这篇文章主要讲解虚继承的C++对象内存分布问题,从中也引出了dynamic_cast和static_cast本质区别.虚函数表的格式等一些大部分C++程序员都似是而非的概念.原文见这里(By Edsko de Vries, January 2006) 敬告: 本文是介绍C++的技术文章,假定读者对于C++有比较深入的认识,同时也需要一些汇编知识. 本文我们将阐释GCC编译器针对多重继承和虚拟继承下的对象内存布局.尽管在理想的使用环境中,一个C++程序员并不需要了解这些编译器内部实现细节,实际上,

虚继承的内存布局手札1——基于VS2012

1.纸上得来总觉浅,低头debug才深刻. 对于<深度探索C++对象模型>这类型的书,得到的知识要去及时巩固才能实现永久记忆. 2.在实现了了虚拟继承归并分支之后的内容布局跟虚表的可复用存在极大关系. 继承的顺序决定了A和B的布局顺序,然后Common则在高地址,即公虚基类的布局放在D的尾部. 情况1: class A:public virtual Common{...}; class B:public virtual Common{...;virtual void NotInCommon()

C++ 多继承和虚继承的内存布局(Memory Layout for Multiple and Virtual Inheritance)

警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能预见到这些结论并运用到你的代码中.而且,如果你关心性能,理解虚拟继承的开销也是非常有用的.最后,这很有趣. :-) 多重