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;}
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})
|
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
|
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
|
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
|
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
|
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
|
[原理最清晰]
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++各种类继承关系的内存布局的更多相关文章
- 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局
继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...
- c++继承中的内存布局
今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化 译 译者前言 一个C ...
- 从汇编看c++的虚拟继承以及其内存布局(一)
先看第一种最简单的情形,所有类中没有任何虚函数的菱形继承. 下面是c++源码: class Top {//虚基类 public: int i; Top(int ii) { i = ii; } }; c ...
- C++对象模型:单继承,多继承,虚继承,菱形虚继承,及其内存布局图
C++目前使用的对象模型: 此模型下,nonstatic数据成员被置于每一个类的对象中,而static数据成员则被置于类对象之外,static和nonstatic函数也都放在类对象之外(通过函数指针指 ...
- 继承关系在内存和DB中的映射
使用 将若干相似的类映射为单表,对拥有许多特殊数据的类使用具体表继承. 对高层次使用类表继承,对低层次使用具体表继承. Single Table Inheritance 在DB中将类继承层次设计为一个 ...
- C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布
1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...
- 转: c++继承中的内存布局
英文原文: http://www.openrce.org/articles/files/jangrayhood.pdf 翻译: http://blog.csdn.net/jiangyi711/arti ...
- 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。
本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...
- 虚继承之单继承的内存布局(VC在编译时会把vfptr放到类的头部,这和Delphi完全一致)
C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内 ...
随机推荐
- python logging日志输出个文件中
# -*- coding:utf-8 -*- import logging # 引入logging模块 import os.path import time # 第一步,创建一个logger logg ...
- Spring AOP 理论
一.AOP AOP 产生的背景 “存在即合理”,任何一种理论或技术的产生,必然有它的原因.了解它产生的背景.为了解决的问题有助于我们更好地把握AOP的概念. 软件开发一直在寻求一种高效开发.护展.维护 ...
- centos7: php7.2.9安装配置
下载php http://cn2.php.net/distributions/php-7.2.9.tar.gz 解压到: /usr/local/src/ 接下来进行参数配置,配置前如果没有libxml ...
- 概率分布之间的推导关系 | Univariate Distribution Relationships
Univariate Distribution Relationships APPL: A Probability Programming Language Maplesoft- Software f ...
- English Voice of <<All Of Me>>
"All Of Me"我的一切 [Verse 1:]What would I do without your smart mouth没有你的蜜语甜言,我该怎办Drawing me ...
- LeetCode--367--有效的完全平方数
问题描述: 给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False. 说明:不要使用任何内置的库函数,如 sqrt. 示例 1: 输入:16 输 ...
- jQuery -- touch事件之滑动判断(左右上下方向)
$("body").on("touchstart", function(e) { // 判断默认行为是否可以被禁用 if (e.cancelable) { // ...
- Gifts by the List CodeForces - 681D (思维)
大意: 给定森林, 要求构造一个表, 满足对于每个$x$, 表中第一次出现的$x$的祖先(包括$x$)是$a_x$. 刚开始还想着直接暴力分块优化一下连边, 最后按拓扑序输出... 实际上可以发现$a ...
- loj#6062. 「2017 山东一轮集训 Day2」Pair hall定理+线段树
题意:给出一个长度为 n的数列 a和一个长度为 m 的数列 b,求 a有多少个长度为 m的连续子数列能与 b匹配.两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当 ...
- 【PowerDesigner】【7】Table视图显示Comment
原理:把显示name的列的值,替换成注释的值. 步骤:打开菜单Tools>Execute Commands>Edit/Run Script.. 或者用快捷键 Ctrl+Shift+X.将下 ...