C++对象模型-3

前言


前一篇主要介绍了C++对象在普通单继承和普通多继承体系下的对象模型,没有考虑到虚继承的情况。接下来将从虚拟单继承,虚拟多继承(包括一部分虚继承和全部虚继承)等几种继承方式下分别探究下C++对象模型的特点,如未特别说明,所有虚拟继承体系下的基类实现代码与前一篇是一致的

虚拟继承


单虚拟继承的子类


简单实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Single Virtual Derive: Second Inheritance Level
class Derive_Sin_Vir : virtual public Base
{
public:
Derive_Sin_Vir(int var = 40) : Base(var), _derive_sin_vir_var(var) {};
public:
virtual void Run(void) // override Base::Run()
{
std::cout << "Derive_Sin_Vir Class Run()" << std::endl;
}
virtual void RunDerive_Sin_Vir(void) // new virtual function
{
std::cout << "Derive_Sin_Vir Class RunDerive_Sin_Vir()" << std::endl;
}
private:
int _derive_sin_vir_var;
};

Gcc命令的内存布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Vtable for Derive_Sin_Vir
Derive_Sin_Vir::_ZTV14Derive_Sin_Vir: 11 entries
0 16
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI14Derive_Sin_Vir)
24 (int (*)(...))Derive_Sin_Vir::Run
32 (int (*)(...))Derive_Sin_Vir::RunDerive_Sin_Vir
40 0
48 18446744073709551600
56 (int (*)(...))-16
64 (int (*)(...))(& _ZTI14Derive_Sin_Vir)
72 (int (*)(...))Derive_Sin_Vir::_ZTv0_n24_N14Derive_Sin_Vir3RunEv
80 (int (*)(...))Base::RunBase

VTT for Derive_Sin_Vir
Derive_Sin_Vir::_ZTT14Derive_Sin_Vir: 2 entries
0 ((& Derive_Sin_Vir::_ZTV14Derive_Sin_Vir) + 24)
8 ((& Derive_Sin_Vir::_ZTV14Derive_Sin_Vir) + 72)

Class Derive_Sin_Vir
size=32 align=8
base size=12 base align=8
Derive_Sin_Vir (0x0x7fb40baf95b0) 0
vptridx=0 vptr=((& Derive_Sin_Vir::_ZTV14Derive_Sin_Vir) + 24)
Base (0x0x7fb40baf0780) 16 virtual
vptridx=8 vbaseoffset=-24 vptr=((& Derive_Sin_Vir::_ZTV14Derive_Sin_Vir) + 72)

可以看到单虚拟继承的子类的内存空间特点是新建的子类虚表内存布局+虚基类的内存布局。子类自己的内存布局包括自己生成的虚函数表,里面包含虚函数列表和虚表以及虚基表偏移和子类的成员变量;虚基类的内存布局包括基类的虚函数表和基类的成员变量。子类的新增的虚函数或重写对的虚函数是在自己生成的虚函数表中的;而虚基类的未重写虚函数则是在继承而来的基类的虚基表中。

内存布局的代码验证

1.测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void SingleVirtualDeriveTest(void)
{
Derive_Sin_Vir d;
std::cout << "---------begin single virtual derive object inner memory layout test-------" << std::endl;

std::cout << " object size is: " << sizeof(d) << std::endl;
std::cout << " object addr is: " << &d << std::endl; // d指针转换为long指针
std::cout << " typeid(d) is: " << typeid(d).name() << std::endl; // d对象类型
std::cout << " object vfptr value is: " << (long*)*(long*)&d << std::endl; // derive vfptr地址 在对象第1个位置

std::cout << " object vfptr[0] func ptr is: " << (long*)*(long*)(*(long*)&d) << std::endl; //vfptr[0]
std::cout << " object vfptr[0] func invoke res: ";
pFunc pRun = (pFunc)(*(long*)(*(long*)&d));
(*pRun)(); //调用vfptr[0](函数地址值)指向的函数

std::cout << " object vfptr[1] addr is: " << (long*)(*((long*)(*(long*)&d) + 1)) << std::endl; //vfptr[1]
std::cout << " object vfptr[1] func invoke res: ";
pFunc pRunDerive_Sin_Vir = (pFunc)((long*)(*((long*)(*(long*)&d) + 1)));
(*pRunDerive_Sin_Vir)(); //调用vfptr[1](函数地址值)指向的函数

std::cout << " object vfptr[2] vptr offset value is: " << (int)(*((long*)(*(long*)&d) + 2)) << std::endl; // vfptr[2]
std::cout << " object vfptr[3] vbase offset value is: " << (int)(*((long*)(*(long*)&d) + 3)) << std::endl; // vfptr[3]

std::cout << " object _derive_sin_vir_var addr is: " << (long*)&d + 1 << std::endl; //_derive_sin_vir_var 在对象第2个位置
std::cout << " object _derive_sin_vir_var value is: " << (int)*((long*)&d + 1) << std::endl;

std::cout << " object vfptr-base addr is: " << (long*)&d + 2 << std::endl; //vfptr-base 在对象第3个位置
std::cout << " object vfptr-base value is: " << (long*)(*((long*)&d + 2)) << std::endl;

std::cout << " object vfptr-base[0] func ptr is: " << (long*)(*((long*)(*((long*)&d + 2)) + 0)) << std::endl;// vfptr-base[0]
// std::cout << " object vfptr-base[0] func invoke res: ";
// pFunc pRunGenInner = (pFunc)(*((long*)(*((long*)&d + 2)) + 0));
// (*pRunGenInner)(); //调用vfptr-base[0](函数地址值)指向的函数,内部生成函数无法运行
std::cout << " object vfptr-base[1] func ptr is: " << (long*)(*((long*)(*((long*)&d + 2)) + 1)) << std::endl; //vfptr-base[1]
std::cout << " object vfptr-base[1] func invoke res: ";
pFunc pRunBase = (pFunc)(*((long*)(*((long*)&d + 2)) + 1));
(*pRunBase)(); //调用vfptr-base[1](函数地址值)指向的函数

std::cout << " object _base_var addr is: " << (long*)&d + 3 << std::endl; //_base_var 在对象第4个位置
std::cout << " object _base_var value is: " << (int)*((long*)&d + 3) << std::endl;

std::cout << "---------end single virtual derive object inner memory layout test-------" << std::endl;
}

2.运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
---------begin single virtual derive object inner memory layout test-------
object size is: 32
object addr is: 0x7ffe2ac9df60
typeid(d) is: 14Derive_Sin_Vir
object vfptr value is: 0x5580dd6a9878
object vfptr[0] func ptr is: 0x5580dd6a4e96
object vfptr[0] func invoke res: Derive_Sin_Vir Class Run()
object vfptr[1] addr is: 0x5580dd6a4ede
object vfptr[1] func invoke res: Derive_Sin_Vir Class RunDerive_Sin_Vir()
object vfptr[2] vptr offset value is: 0
object vfptr[3] vbase offset value is: -16
object _derive_sin_vir_var addr is: 0x7ffe2ac9df68
object _derive_sin_vir_var value is: 40
object vfptr-base addr is: 0x7ffe2ac9df70
object vfptr-base value is: 0x5580dd6a98a8
object vfptr-base[0] func ptr is: 0x5580dd6a4ed1
object vfptr-base[1] func ptr is: 0x5580dd6a4d62
object vfptr-base[1] func invoke res: Base Class RunBase()
object _base_var addr is: 0x7ffe2ac9df78
object _base_var value is: 40
---------end single virtual derive object inner memory layout test-------

3.内存布局示意图:
single virtual derive

多虚拟继承的子类(Half)


简单实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Multi Half Virtual Derive: Second Inheritance Level
class Derive_Half_Mul_Vir : virtual public Base, public Base2
{
public:
Derive_Half_Mul_Vir(int var = 50) : Base(var), Base2(var), _derive_half_mul_vir_var(var) {};
public:
virtual void Run(void) // override Base::Run()
{
std::cout << "Derive_Half_Mul_Vir Class Run()" << std::endl;
}
virtual void RunBase2(void) // override Base2::RunBase2()
{
std::cout << "Derive_Half_Mul_Vir Class RunBase2()" << std::endl;
}
virtual void RunDerive_Half_Mul_Vir(void) // new virtual function
{
std::cout << "Derive_Half_Mul_Vir Class RunDerive_Half_Mul_Vir()" << std::endl;
}
private:
int _derive_half_mul_vir_var;
};

Gcc命令的内存布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Vtable for Derive_Half_Mul_Vir
Derive_Half_Mul_Vir::_ZTV19Derive_Half_Mul_Vir: 12 entries
0 16
8 (int (*)(...))0
16 (int (*)(...))(& _ZTI19Derive_Half_Mul_Vir)
24 (int (*)(...))Derive_Half_Mul_Vir::Run
32 (int (*)(...))Derive_Half_Mul_Vir::RunBase2
40 (int (*)(...))Derive_Half_Mul_Vir::RunDerive_Half_Mul_Vir
48 0
56 18446744073709551600
64 (int (*)(...))-16
72 (int (*)(...))(& _ZTI19Derive_Half_Mul_Vir)
80 (int (*)(...))Derive_Half_Mul_Vir::_ZTv0_n24_N19Derive_Half_Mul_Vir3RunEv
88 (int (*)(...))Base::RunBase

VTT for Derive_Half_Mul_Vir
Derive_Half_Mul_Vir::_ZTT19Derive_Half_Mul_Vir: 2 entries
0 ((& Derive_Half_Mul_Vir::_ZTV19Derive_Half_Mul_Vir) + 24)
8 ((& Derive_Half_Mul_Vir::_ZTV19Derive_Half_Mul_Vir) + 80)

Class Derive_Half_Mul_Vir
size=32 align=8
base size=16 base align=8
Derive_Half_Mul_Vir (0x0x7fb40bf40af0) 0
vptridx=0 vptr=((& Derive_Half_Mul_Vir::_ZTV19Derive_Half_Mul_Vir) + 24)
Base (0x0x7fb40bb61360) 16 virtual
vptridx=8 vbaseoffset=-24 vptr=((& Derive_Half_Mul_Vir::_ZTV19Derive_Half_Mul_Vir) + 80)
Base2 (0x0x7fb40bb613c0) 0
primary-for Derive_Half_Mul_Vir (0x0x7fb40bf40af0)

可以看到多虚拟继承的子类(Half)的内存空间特点是普通继承基类内存布局+子类自己的内存布局+虚基类的内存布局。普通继承基类的内存布局包括普通继承而来的基类虚函数表和普通继承基类的成员变量;子类自己内存布局包括继承而来的普通基类的虚函数表和子类的成员变量。子类的虚函数则是在普通继承而来的基类的虚函数表基础上进行新增、替换(override)、保持操作(没有override),虚基类的内存布局包括虚基类表和虚基类成员变量。

内存布局的代码验证

1.测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void HalfMultiVirtualDeriveTest(void)
{
Derive_Half_Mul_Vir d;
std::cout << "---------begin half multi virtual derive object inner memory layout test-------" << std::endl;

std::cout << " object size is: " << sizeof(d) << std::endl;
std::cout << " object addr is: " << &d << std::endl; // d指针转换为long指针
std::cout << " typeid(d) is: " << typeid(d).name() << std::endl; // d对象类型
std::cout << " object vfptr value is: " << (long*)*(long*)&d << std::endl; // derive(base2) vfptr地址 在对象第1个位置
std::cout << " object vfptr[0] func ptr is: " << (long*)*(long*)(*(long*)&d) << std::endl; //vfptr[0]的值
std::cout << " object vfptr[0] func invoke res: ";
pFunc pRun = (pFunc)(*(long*)(*(long*)&d));
(*pRun)(); //调用vfptr[0](函数地址值)指向的函数
std::cout << " object vfptr[1] func ptr is: " << (long*)*((long*)(*(long*)&d) + 1) << std::endl; //vfptr[1]的值
std::cout << " object vfptr[1] func invoke res: ";
pFunc pRunBase2 = (pFunc)(*((long*)(*(long*)&d) + 1));
(*pRunBase2)(); //调用vfptr[1](函数地址值)指向的函数
std::cout << " object vfptr[2] func ptr is: " << (long*)*((long*)(*(long*)&d) + 2) << std::endl; //vfptr[2]的值
std::cout << " object vfptr[2] func invoke res: ";
pFunc pRunDerive_Half_Mul_Vir = (pFunc)(*((long*)(*(long*)&d) + 2));
(*pRunDerive_Half_Mul_Vir)(); //调用vfptr[2](函数地址值)指向的函数
std::cout << " object vfptr[3] vptr offset is: " << (int)*((long*)(*(long*)&d) + 3) << std::endl; //vfptr[3]的值
std::cout << " object vfptr[4] vbase offset is: " << (int)*((long*)(*(long*)&d) + 4) << std::endl; //vfptr[4]的值
std::cout << " object _base2_var addr is: " << (long*)&d + 1 << std::endl; //_base2_var 在对象第2个位置
std::cout << " object _base2_var value is: " << (int)*((long*)&d + 1) << std::endl;
std::cout << " object _derive_half_mul_vir_var addr is: " << (long*)((int*)((long*)&d + 1) + 1) << std::endl; //_derive_half_mul_vir_var 在对象第3个位置
std::cout << " object _derive_half_mul_vir_var value is: " << *((int*)((long*)&d + 1) + 1) << std::endl;

std::cout << " object vfptr-base addr is: " << (long*)&d + 2 << std::endl; // derive vfptr-base 地址 在对象第4个位置
std::cout << " object vfptr-base value is: " << (long*)(*((long*)&d + 2)) << std::endl;
std::cout << " object vfptr-base[0] func ptr is: " << (long*)*((long*)*((long*)&d + 2)) << std::endl; // vbptr-base[0]
// std::cout << " object vfptr-base[0] func invoke res: ";
// pFunc pRun = (pFunc)(*((long*)*((long*)&d + 2)));
// (*pRun)(); //调用vfptr-base[0](函数地址值)指向的函数,内部生成的函数无法调用
std::cout << " object vfptr-base[1] func ptr is: " << (long*)*((long*)*((long*)&d + 2) + 1) << std::endl; // vbptr-base[1]
std::cout << " object vfptr-base[1] func invoke res: ";
pFunc pRunBase = (pFunc)(*((long*)*((long*)&d + 2) + 1));
(*pRunBase)(); //调用vfptr-base[1](函数地址值)指向的函数
std::cout << " object _base_var addr is: " << (long*)&d + 3 << std::endl; //_base_var 在对象第5个位置
std::cout << " object _base_var value is: " << (int)*((long*)&d + 3) << std::endl;

std::cout << "---------end half multi virtual derive object inner memory layout test-------" << std::endl;

}

2.运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---------begin half multi virtual derive object inner memory layout test-------
object size is: 32
object addr is: 0x7ffdac1071e0
typeid(d) is: 19Derive_Half_Mul_Vir
object vfptr value is: 0x5595ce96e808
object vfptr[0] func ptr is: 0x5595ce969f80
object vfptr[0] func invoke res: Derive_Half_Mul_Vir Class Run()
object vfptr[1] func ptr is: 0x5595ce969fc8
object vfptr[1] func invoke res: Derive_Half_Mul_Vir Class RunBase2()
object vfptr[2] func ptr is: 0x5595ce96a004
object vfptr[2] func invoke res: Derive_Half_Mul_Vir Class RunDerive_Half_Mul_Vir()
object vfptr[3] vptr offset is: 0
object vfptr[4] vbase offset is: -16
object _base2_var addr is: 0x7ffdac1071e8
object _base2_var value is: 50
object _derive_half_mul_vir_var addr is: 0x7ffdac1071ec
object _derive_half_mul_vir_var value is: 50
object vfptr-base addr is: 0x7ffdac1071f0
object vfptr-base value is: 0x5595ce96e840
object vfptr-base[0] func ptr is: 0x5595ce969fbb
object vfptr-base[1] func ptr is: 0x5595ce969d62
object vfptr-base[1] func invoke res: Base Class RunBase()
object _base_var addr is: 0x7ffdac1071f8
object _base_var value is: 50
---------end half multi virtual derive object inner memory layout test-------

3.内存布局示意图:
half multi virtual derive

多虚拟继承的子类(Both)


简单实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Multi Both Virtual Derive: Second Inheritance Level
class Derive_Both_Mul_Vir : virtual public Base, virtual public Base2
{
public:
Derive_Both_Mul_Vir(int var = 50) : Base(var), Base2(var), _derive_both_mul_vir_var(var) {};
public:
virtual void Run(void) // override Base::Run()
{
std::cout << "Derive_Both_Mul_Vir Class Run()" << std::endl;
}
virtual void RunBase2(void) // override Base2::RunBase2()
{
std::cout << "Derive_Both_Mul_Vir Class RunBase2()" << std::endl;
}
virtual void RunDerive_Both_Mul_Vir(void) // new virtual function
{
std::cout << "Derive_Both_Mul_Vir Class RunDerive_Both_Mul_Vir()" << std::endl;
}
private:
int _derive_both_mul_vir_var;
};

Gcc命令的内存布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Vtable for Derive_Both_Mul_Vir
Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir: 19 entries
0 32
8 16
16 (int (*)(...))0
24 (int (*)(...))(& _ZTI19Derive_Both_Mul_Vir)
32 (int (*)(...))Derive_Both_Mul_Vir::Run
40 (int (*)(...))Derive_Both_Mul_Vir::RunBase2
48 (int (*)(...))Derive_Both_Mul_Vir::RunDerive_Both_Mul_Vir
56 0
64 18446744073709551600
72 (int (*)(...))-16
80 (int (*)(...))(& _ZTI19Derive_Both_Mul_Vir)
88 (int (*)(...))Derive_Both_Mul_Vir::_ZTv0_n24_N19Derive_Both_Mul_Vir3RunEv
96 (int (*)(...))Base::RunBase
104 18446744073709551584
112 18446744073709551584
120 (int (*)(...))-32
128 (int (*)(...))(& _ZTI19Derive_Both_Mul_Vir)
136 (int (*)(...))Derive_Both_Mul_Vir::_ZTv0_n24_N19Derive_Both_Mul_Vir3RunEv
144 (int (*)(...))Derive_Both_Mul_Vir::_ZTv0_n32_N19Derive_Both_Mul_Vir8RunBase2Ev

VTT for Derive_Both_Mul_Vir
Derive_Both_Mul_Vir::_ZTT19Derive_Both_Mul_Vir: 3 entries
0 ((& Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir) + 32)
8 ((& Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir) + 88)
16 ((& Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir) + 136)

Class Derive_Both_Mul_Vir
size=48 align=8
base size=12 base align=8
Derive_Both_Mul_Vir (0x0x7fb40bf40b60) 0
vptridx=0 vptr=((& Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir) + 32)
Base (0x0x7fb40bb61de0) 16 virtual
vptridx=8 vbaseoffset=-24 vptr=((& Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir) + 88)
Base2 (0x0x7fb40bb61e40) 32 virtual
vptridx=16 vbaseoffset=-32 vptr=((& Derive_Both_Mul_Vir::_ZTV19Derive_Both_Mul_Vir) + 136)

可以看到多虚拟继承的子类(Both)的内存空间特点是**子类自己的内存布局+虚基类的内存布局+虚基类2的内存布局+…**。子类自己的内存布局包括自己生成的虚函数表和子类的成员变量;虚基类的内存布局包括基类的虚函数表和基类的成员变量。子类的新增或重写的虚函数是在自己生成的虚函数表中的;而虚基类中未被重写的虚函数则是在继承而来的相应基类的虚函数表中。

内存布局的代码验证

1.测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
void BothMultiVirtualDeriveTest(void)
{
Derive_Both_Mul_Vir d;
std::cout << "---------begin both multi virtual derive object inner memory layout test-------" << std::endl;

std::cout << " object size is: " << sizeof(d) << std::endl;
std::cout << " object addr is: " << &d << std::endl; // d指针转换为long指针
std::cout << " typeid(d) is: " << typeid(d).name() << std::endl; // d对象类型
std::cout << " object vfptr addr is: " << (long*)*(long*)&d << std::endl; // derive vfptr地址 在对象第1个位置
std::cout << " object vfptr[0] func ptr is: " << (long*)*(long*)(*(long*)&d) << std::endl; //vfptr[0]的值
std::cout << " object vfptr[0] func invoke res: ";
pFunc pRun = (pFunc)(*(long*)(*(long*)&d));
(*pRun)(); //调用vfptr[0](函数地址值)指向的函数

std::cout << " object vfptr[1] func ptr is: " << (long*)*((long*)(*(long*)&d) + 1) << std::endl; //vfptr[1]的值
std::cout << " object vfptr[1] func invoke res: ";
pFunc pRunBase2 = (pFunc)(*((long*)(*(long*)&d) + 1));
(*pRunBase2)(); //调用vfptr[1](函数地址值)指向的函数

std::cout << " object vfptr[2] func ptr is: " << (long*)*((long*)(*(long*)&d) + 2) << std::endl; //vfptr[2]的值
std::cout << " object vfptr[2] func invoke res: ";
pFunc pRunDeriveBothMulVir = (pFunc)(*((long*)(*(long*)&d) + 2));
(*pRunDeriveBothMulVir)(); //调用vfptr[2](函数地址值)指向的函数

std::cout << " object vfptr[3] vptr offset is: " << (int)*((long*)(*(long*)&d) + 3) << std::endl; //vfptr[3]的值
std::cout << " object vfptr[4] vbase offset is: " << (int)*((long*)(*(long*)&d) + 4) << std::endl; //vfptr[4]的值

std::cout << " object _derive_both_mul_vir_var addr is: " << (long*)&d + 1 << std::endl; //_derive_both_mul_vir_var 在对象第2个位置
std::cout << " object _derive_both_mul_vir_var value is: " << (int)*((long*)&d + 1) << std::endl;

std::cout << " object vfptr-base addr is: " << (long*)&d + 2 << std::endl; // derive vfptr-base 地址 在对象第3个位置
std::cout << " object vfptr-base value is: " << (long*)(*((long*)&d + 2)) << std::endl;
std::cout << " object vfptr-base[0] func ptr is: " << (long*)*((long*)*((long*)&d + 2)) << std::endl; // vfptr-base[0]
// std::cout << " object vfptr-base[0] func invoke res: ";
// pFunc pRun = (pFunc)(*(long*)(*((long*)&d + 2)));
// (*pRun)(); //调用vfptr[0](函数地址值)指向的函数,自动生成的函数无法调用
std::cout << " object vfptr-base[1] func ptr is: " << (long*)*((long*)(*((long*)&d + 2)) + 1) << std::endl; //vfptr-base[1]
std::cout << " object vfptr-base[1] func invoke res: ";
pFunc pRunBase = (pFunc)(*((long*)(*((long*)&d + 2)) + 1));
(*pRunBase)(); //调用vfptr[1](函数地址值)指向的函数
std::cout << " object _base_var addr is: " << (long*)&d + 3 << std::endl; //_base_var 在对象第4个位置
std::cout << " object _base_var value is: " << (int)*((long*)&d + 3) << std::endl;

std::cout << " object vfptr-base2 addr is: " << (long*)&d + 4 << std::endl; // derive vfptr-base 地址 在对象第5个位置
std::cout << " object vfptr-base2 value is: " << (long*)(*((long*)&d + 4)) << std::endl;
std::cout << " object vfptr-base2[0] func ptr is: " << (long*)*((long*)*((long*)&d + 4)) << std::endl; // vfptr-base2[0]
// std::cout << " object vfptr-base2[0] func invoke res: ";
// pFunc pRunGen1 = (pFunc)(*(long*)(*((long*)&d + 4)));
// (*pRun)(); //调用vfptr[0](函数地址值)指向的函数,自动生成的函数无法调用
std::cout << " object vfptr-base2[1] func ptr is: " << (long*)*((long*)(*((long*)&d + 4)) + 1) << std::endl; //vfptr-base2[1]
// std::cout << " object vfptr-base2[1] func invoke res: ";
// pFunc pRunGeGen2 = (pFunc)(*((long*)(*((long*)&d + 4)) + 1));
// (*pRunGen2)(); Gen2调用vfptr[1](函数地址值)指向的函数
std::cout << " object _base2_var addr is: " << (long*)&d + 5 << std::endl; //_base2_var 在对象第6个位置
std::cout << " object _base2_var value is: " << (int)*((long*)&d + 5) << std::endl;

std::cout << "---------end both multi virtual derive object inner memory layout test-------" << std::endl;

}

2.运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
---------begin both multi virtual derive object inner memory layout test-------
object size is: 48
object addr is: 0x7ffdf308a520
typeid(d) is: 19Derive_Both_Mul_Vir
object vfptr addr is: 0x55dbd6a85760
object vfptr[0] func ptr is: 0x55dbd6a810bc
object vfptr[0] func invoke res: Derive_Both_Mul_Vir Class Run()
object vfptr[1] func ptr is: 0x55dbd6a81104
object vfptr[1] func invoke res: Derive_Both_Mul_Vir Class RunBase2()
object vfptr[2] func ptr is: 0x55dbd6a8114c
object vfptr[2] func invoke res: Derive_Both_Mul_Vir Class RunDerive_Both_Mul_Vir()
object vfptr[3] vptr offset is: 0
object vfptr[4] vbase offset is: -16
object _derive_both_mul_vir_var addr is: 0x7ffdf308a528
object _derive_both_mul_vir_var value is: 50
object vfptr-base addr is: 0x7ffdf308a530
object vfptr-base value is: 0x55dbd6a85798
object vfptr-base[0] func ptr is: 0x55dbd6a810f7
object vfptr-base[1] func ptr is: 0x55dbd6a80d62
object vfptr-base[1] func invoke res: Base Class RunBase()
object _base_var addr is: 0x7ffdf308a538
object _base_var value is: 50
object vfptr-base2 addr is: 0x7ffdf308a540
object vfptr-base2 value is: 0x55dbd6a857c8
object vfptr-base2[0] func ptr is: 0x55dbd6a810f7
object vfptr-base2[1] func ptr is: 0x55dbd6a8113f
object _base2_var addr is: 0x7ffdf308a548
object _base2_var value is: 50
---------end both multi virtual derive object inner memory layout test-------

3.内存布局示意图:
both multi virtual derive

总结


本篇主要介绍了C++类在虚拟继承下的子类对象内存特点,可以看出,子类新建的或普通继承而来的虚表中存放着子类的虚函数和表偏移值;对于纯虚继承,即所有基类均是虚拟继承(包括但不限于单虚拟继承)来说,子类对象中的新增的虚函数均是在自己生成的新虚函数表中进行操作的(若子类没有新增的虚函数或重写则不需要生成)。而对于不纯情况,子类会类似于前一篇描述的普通继承情况,使用普通继承而来的基类的虚函数表,而不会自己生成。可见,虚拟继承体系下通常情况下会存在多张虚函数表(子类普通继承而来的和某些情况下自己新生成的)。