#include <iostream>
using namespace std;
// 多重继承构造执行顺序:
// 1、首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;
// 2、执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;
// 3、执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;
// 4、执行派生类自己的构造函数;
// 5、析构以与构造相反的顺序执行;
// 继承关系:
// X
// Y Z
// A
class X
{
// virtual void func() { } // 4,8,8,12
};
// C++使用虚拟继承(Virtual Inheritance),使得派生类如果继承基类多次,但只有一份基类的拷贝在派生类对象中。
class Y : public virtual X
{};
class Z : public virtual X
{};
class A : public Y, public Z
{};
class X1
{
public:
// virtual void func() { } // 4,4,4,8
};
class Y1 : public X1
{};
class Z1 : public X1
{};
class A1 : public Y1, public Z1
{};
int main()
{
cout << "sizeof(X): " << sizeof(X) << endl; // 1
cout << "sizeof(Y): " << sizeof(Y) << endl; // 4 这个值和机器有关,也和编译器有关(4或8)
cout << "sizeof(Z): " << sizeof(Z) << endl; // 4
cout << "sizeof(A): " << sizeof(A) << endl; // 8
cout << "sizeof(X1): " << sizeof(X1) << endl; // 1
cout << "sizeof(Y1): " << sizeof(Y1) << endl; // 1
cout << "sizeof(Z1): " << sizeof(Z1) << endl; // 1
cout << "sizeof(A1): " << sizeof(A1) << endl; // 1
return 0;
}
VS2005中,项目属性——>C++——>命令行——>附加选项,设置/d1reportAllClassLayout,编译时在输出中显示出类对象的布局:
1>class X size(1):
1> +---
1> +---
1>class Y size(4):
1> +---
1> 0 | {vbptr}
1> +---
1> +--- (virtual base X)
1> +---
1>Y::$vbtable@:
1> 0 | 0
1> 1 | 4 (Yd(Y+0)X)
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> X 4 0 4 0
1>class Z size(4):
1> +---
1> 0 | {vbptr}
1> +---
1> +--- (virtual base X)
1> +---
1>Z::$vbtable@:
1> 0 | 0
1> 1 | 4 (Zd(Z+0)X)
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> X 4 0 4 0
1>class A size(8):
1> +---
1> | +--- (base class Y)
1> 0 | | {vbptr}
1> | +---
1> | +--- (base class Z)
1> 4 | | {vbptr}
1> | +---
1> +---
1> +--- (virtual base X)
1> +---
1>A::$vbtable@Y@:
1> 0 | 0
1> 1 | 8 (Ad(Y+0)X)
1>A::$vbtable@Z@:
1> 0 | 0
1> 1 | 4 (Ad(Z+0)X)
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> X 8 0 4 0
1>class X1 size(1):
1> +---
1> +---
1>class Y1 size(1):
1> +---
1> | +--- (base class X1)
1> | +---
1> +---
1>class Z1 size(1):
1> +---
1> | +--- (base class X1)
1> | +---
1> +---
1>class A1 size(1):
1> +---
1> | +--- (base class Y1)
1> | | +--- (base class X1)
1> | | +---
1> | +---
1> | +--- (base class Z1)
1> | | +--- (base class X1)
1> | | +---
1> | +---
1> +---
由类对象布局可知:在虚拟继承时,在派生类对象中会有一个vbptr,而在基类中会有一个vbtable。同样方法可以在基类中添加一个虚函数,则可以看到派生对象中会有一个vfptr,而在基类中会有一个vftable。其中vbptr或者vfptr是在派生类定义对象是才有的,而vbtable和vftable则是在基类定义类时就有了。
另外在类不包含任何成员时,类对象仍然是占用空间的(VS2005是1个字节),这样是使得这个类的两个对象得以在内存中配置独一无二的地址。而在类中包含有成员变量或者虚函数时这个编译器安插的一个字节就不需要了。