#include <iostream>
using namespace std;
class Grand //爷爷类
{
public:
int m_grand;
};
class A1 : virtual public Grand
{
public:
int m_a1;
};
class A2 : virtual public Grand
{
public:
int m_a2;
};
class C1 :public A1, public A2
{
public:
int m_c1;
};
int main()
{
//一:三层结构时虚基类表内容分析
cout << sizeof(Grand) << endl;//4
cout << sizeof(A1) << endl;//24
cout << sizeof(A2) << endl;//24
cout << sizeof(C1) << endl;//48
C1 c1obj;
c1obj.m_grand = 2;
c1obj.m_a1 = 5;
c1obj.m_a2 = 6;
c1obj.m_c1 = 8;
//C1 c2obj;
//给m_grand赋值时没有用到vbptr2,只用到了vbptr1
//二:虚基类为什么这么设计
//为什么这么设计,是个很难回答的问题;
//这里不是多态,没有虚函数
A2* pa2 = &c1obj;
if (int(pa2) == int(&c1obj)+16 )
cout << "pa2指向第二个虚基类指针所在的空间" << endl;//√
pa2->m_grand = 8;
pa2->m_a2 = 9;
return 1;
}
类C1的对象空间布局:
A1来的虚基类指针, m_a1, 补齐,A2来的虚基类指针,m_a2, 补齐,C1自身变量m_c1,补齐,爷爷类成员m_grand,补齐。
1.可以看到第一个虚基类指针0x00007FF7A1049C48指向的空间值:
5-8字节表示偏移40字节,“虚基类表指针”成员变量的首地址 + 这个偏移量 就等于 虚基类对象首地址(这里是m_grand首地址)。跳过这个偏移值,我们就能够访问到虚基类对象。
1-4字节:虚基类表指针成员变量的首地址 ,和本对象C1中A1部分首地址之间的偏移量 也就是:虚基类表指针 的首地址 - C1中A1部分对象的首地址,这里正好为0。
2.第二个虚基类指针0x00007FF7A1049C58指向的空间值:
5-8字节表示偏移24字节,“虚基类表指针”成员变量的首地址 + 这个偏移量 就等于 虚基类对象首地址(这里是m_grand首地址)。跳过这个偏移值,我们就能够访问到虚基类对象。
1-4字节:虚基类表指针成员变量的首地址 ,和本对象C1中A2部分首地址之间的偏移量 也就是:虚基类表指针 的首地址 - C1中A2部分对象的首地址,这里正好为0。