C++对象内存模型探究模型
转载注明出处:https://www.zhihu.com/people/peng-cheng-17-51
作者:Cheng游戏开发
前言:
- C++的基于继承关系动态多态特性可以允许父子继承关系的类之间重写函数
- 编译器会在存在虚函数的对象中塞入一个虚表指针,指向一个虚表
- 表内装了我们们所重写的虚函数
- 还讨论了多继承下虚继承相关内容
- 还有内存分布规则
目的:
探究虚表与虚函数在对象中的内存占用情况
前置知识
this指针的内部调整
代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Datainfo
{
int** _ptr;
string _dataInfo;
void PrintSelf()
{
cout << _dataInfo;
while (_dataInfo.size() < 40)
{
_dataInfo.append(" ");
cout << ' ';
}
cout << _ptr << endl;
}
};
bool GreaterSort(Datainfo& Left, Datainfo& Right)
{
return Left._ptr < Right._ptr;
}
std::vector<Datainfo> StructDataInfo;
typedef void(*FUNC)();
void PrintVTable(int**& VTable)
{
std::cout << " 虚表函数地址: " << VTable << std::endl;
for (int i = 0; (VTable[i]) != NULL; ++i)
{
__try
{
FUNC f = (FUNC)VTable[i];
f();
printf("<-第%d个虚函数地址: 0X%x,\n", i, VTable[i]);
}
__except (1)
{
std::cout << " 虚表函数结束 " << std::endl;
break;
}
}
std::cout << std::endl;
}
void PrintAllData()
{
std::cout << "输出所有" << endl;
std::sort(StructDataInfo.begin(), StructDataInfo.end(), GreaterSort);
for (auto var : StructDataInfo)
{
var.PrintSelf();
}
}
class Interface_PointA
{
public:
void PrintInterface_PointA()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointA Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
}
int _a = 0;
void PrintVPtrTableA()
{
std::cout << "Interface_PointA的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointA_1() {
std::cout << " Interface_PointA::Interface_PointA_1 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
};
class Interface_PointB
{
public:
int _b = 0;
void PrintInterface_PointB()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointB Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableB()
{
std::cout << "Interface_PointB的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointB_1() {
std::cout << " Interface_PointB::Interface_PointB_1 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointB:: BaseFunction ";
};
};
class Point3D :public Interface_PointA, public Interface_PointB
{
public:
void PrintPoint3D()
{
Datainfo NewData;
NewData._dataInfo = "Point3D Start this is:";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_Point3Data is :";
NewData._ptr = (int**)&this->_Point3Data;
StructDataInfo.push_back(NewData);
PrintInterface_PointA();
PrintInterface_PointB();
}
void PrintVPtrTablePoint3D()
{
std::cout << "Point3D的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
virtual void Interface_PointB_1() {
std::cout << " Point3D::Interface_PointB_1 ";
}
virtual void Interface_PointA_1() {
std::cout << " Point3D::Interface_PointA_1 ";
}
void PrintVPtrTable()
{
PrintVPtrTableB();
PrintVPtrTableA();
PrintVPtrTablePoint3D();
}
virtual void Point3D_1() {
std::cout << " Point3D::Point3D_1 ";
}
virtual void Point3D_2() {
std::cout << "Point3D:: Point3D_2 ";
}
int _Point3Data = 0;
virtual void BaseFunction() override {
std::cout << " Point3D::BaseFunction ";
};
};
int main()
{
Point3D TestChildInstance = Point3D();
TestChildInstance.PrintPoint3D();
std::cout << "sizeof(void*) is " << sizeof(void*) << std::endl;
std::cout << "sizeof(int) is " << sizeof(int) << std::endl;
std::cout << "sizeof(Point3D) is " << sizeof(Point3D) << std::endl;
PrintAllData();
TestChildInstance.PrintVPtrTable();
return 0;
}
总结:
我们可以看到在C++的继承关系下
在子类实例的不同继承层里面的 this指针 其实是指向不同位置的
一般都是指向对应继承父类的开头位置
虚表指针与虚表
- 我们可以看到,子类 Point3D 和基类 Interface_PointA 共用 了一个虚表指针,而且指向同一个虚表
- 虚表一般占用的是每个类实例的 this 指针的头 8 个字节
- 在这种情况下,其实我们可以看到普通继承中其实是存在主次要关系的
- 普通继承中主次要继承关系的决定因素:
- 有虚指针的优先级更高
- 同优先级按照继承顺序排
验证普通继承关系是否存在主次要继承
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Datainfo
{
int** _ptr;
string _dataInfo;
void PrintSelf()
{
cout << _dataInfo;
while (_dataInfo.size() < 40)
{
_dataInfo.append(" ");
cout << ' ';
}
cout << _ptr << endl;
}
};
bool GreaterSort(Datainfo& Left, Datainfo& Right)
{
return Left._ptr < Right._ptr;
}
std::vector<Datainfo> StructDataInfo;
typedef void(*FUNC)();
void PrintVTable(int**& VTable)
{
std::cout << " 虚表函数地址: " << VTable << std::endl;
for (int i = 0; (VTable[i]) != NULL; ++i)
{
__try
{
FUNC f = (FUNC)VTable[i];
f();
printf("<-第%d个虚函数地址: 0X%x,\n", i, VTable[i]);
}
__except (1)
{
std::cout << " 虚表函数结束 " << std::endl;
break;
}
}
std::cout << std::endl;
}
void PrintAllData()
{
std::cout << "输出所有" << endl;
std::sort(StructDataInfo.begin(), StructDataInfo.end(), GreaterSort);
for (auto var : StructDataInfo)
{
var.PrintSelf();
}
}
class Interface_PointA
{
public:
void PrintInterface_PointA()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointA Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
}
int _a = 0;
void PrintVPtrTableA()
{
std::cout << "Interface_PointA的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
};
class Interface_PointB
{
public:
int _b = 0;
void PrintInterface_PointB()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointB Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableB()
{
std::cout << "Interface_PointB的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointB_1() {
std::cout << " Interface_PointB::Interface_PointB_1 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointB:: BaseFunction ";
};
};
class Interface_PointC
{
public:
int _c = 0;
void PrintInterface_PointC()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointC Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableC()
{
std::cout << "Interface_PointC的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointC_1() {
std::cout << " Interface_PointC::Interface_PointB_1 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointC:: BaseFunction ";
};
};
class Point3D :public Interface_PointA, public Interface_PointB, public Interface_PointC
{
public:
void PrintPoint3D()
{
Datainfo NewData;
NewData._dataInfo = "Point3D Start this is:";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_Point3Data is :";
NewData._ptr = (int**)&this->_Point3Data;
StructDataInfo.push_back(NewData);
PrintInterface_PointA();
PrintInterface_PointB();
PrintInterface_PointC();
}
void PrintVPtrTablePoint3D()
{
std::cout << "Point3D的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
virtual void Interface_PointB_1() {
std::cout << " Point3D::Interface_PointB_1 ";
}
virtual void Interface_PointA_1() {
std::cout << " Point3D::Interface_PointA_1 ";
}
void PrintVPtrTable()
{
PrintVPtrTableC();
PrintVPtrTableB();
PrintVPtrTableA();
PrintVPtrTablePoint3D();
}
virtual void Point3D_1() {
std::cout << " Point3D::Point3D_1 ";
}
virtual void Point3D_2() {
std::cout << "Point3D:: Point3D_2 ";
}
int _Point3Data = 0;
virtual void BaseFunction() override {
std::cout << " Point3D::BaseFunction ";
};
virtual void Interface_PointC_1() {
std::cout << " Interface_PointC::Interface_PointB_1 ";
}
};
int main()
{
Point3D TestChildInstance = Point3D();
TestChildInstance.PrintPoint3D();
std::cout << "sizeof(void*) is " << sizeof(void*) << std::endl;
std::cout << "sizeof(int) is " << sizeof(int) << std::endl;
std::cout << "sizeof(Point3D) is " << sizeof(Point3D) << std::endl;
PrintAllData();
TestChildInstance.PrintVPtrTable();
return 0;
}
普通继承中的内存顺序也取决于这个
- 有虚指针的优先级更高
- 同优先级按照继承顺序排
虚表指针的覆盖
虚表中的函数以什么规则出现的?出现在哪里?
- 虚函数只会出现第一次被声明的类所拥有的虚表中
子类重写的话,重写到了哪里?为什么这么做?
- 虚函数的重写会覆盖到每一个基类的持有这个函数的虚表中
为什么会这么做?
一切目的是为了兼容多态用法
class Interface_PointA
{
virtual void BaseFunction();
};
class Interface_PointB
{
virtual void BaseFunction();
};
class Point3D:Interface_PointA,Interface_PointB
{
virtual void BaseFunction();
};
Interface_PointA *p = new Point3D();
Interface_PointB *p1 = new Point3D();
p1->BaseFunction();
首先BaseFunction在Interface_PointA和Interface_PointB的虚表中都存在
因为:
对于Interface_PointA来说,BaseFunction是在这个继承链上第一次出现的虚函数。
对于Interface_PointB来说,BaseFunction是在这个继承链上第一次出现的虚函数。
假设要调用 Interface_PointA 的指针 P 的 BaseFunction
其实是调用子类重写过的 BaseFunction
在拿到 p 的时候,会根据其指针类型 Interface_PointA ,
找到其 this 指向的地方,再找到其虚表的对应的 BaseFunction 。 p1 也是如此。
所以 Point3D 的 BaseFunction 直接覆盖到 Interface_PointA 和 Interface_PointB 的虚表中
可以保证在不知道是什么具体子类实例是什么的情况下,正确调用到被重写的函数。
内存分布会是什么样的呢?
- 优先有虚函数的排布,之后排布没有虚函数的。
- 都有虚函数同层基类之间按照继承顺序排序。
虚继承的内存分布与寻址方式
虚继承的作用:保证菱形继承情况下,同名变量只有一个
虚继承表
- 虚继承情况,虚表指针的位置
- 如果在类开头没有虚函数表指针的话,虚继承表就占前8个字节
- 如果在类开头有虚函数表指针的话,虚继承表指针排在虚函数表指针后面
- 虚继承情况,虚表指针的内容(全虚继承)
- 第一个值是当前虚表指针到当前的this指针的偏移量
- 第二个是当前虚基类到其继承顺序继承下的最基类的距离
- 之后的按照第二条规则往下排序,之后是最基类的上一层
- 此顺序也顺应于内存排布
举个例子:
class Point0
{
int a;
};
class Point1 :virtual public Point0
{
int a;
};
class Point21
{
int a;
};
class Point22 :virtual public Point1
{
int a;
};
class Point31 :virtual public Point21
{
int a;
};
class Point32 :virtual public Point22
{
int a;
};
class PointFinal:virtual public Point31, virtual public Point32
{
int a;
};
分析
- 内存分布:
- PointFinal 先虚继承 Point31
- Point31 虚继承 Point21 ,把最基类的 Point21 排到第二位,然后后面是 Point31
- 之后开始把第二条虚继承链开始塞入结构
- 先找到最基类 Point0 ,塞到 Point31 后面,然后是 Point0 的上一层 Point1 ,
- 然后是 Point22 ,然后是再上一层的Point32
- 虚表分析:
PointFinal(vbptr)
PointFinal的虚表中存着它所有虚父类的偏移量
0 到自己的 this 偏移量
16 到内存分布中第一个 PointFinal虚继承基类的偏移量
24 到内存分布中第二个 PointFinal虚继承基类的偏移量
40 到内存分布中第三个 PointFinal虚继承基类的偏移量
…
Point22(vbptr)
Point22的虚表中存着它所有虚父类的偏移量
0
-24 到 Point0 的偏移量
-16 到 Point1 的偏移量
…
三个基类继承下无虚继承下的情况:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Datainfo
{
int** _ptr;
string _dataInfo;
void PrintSelf()
{
cout << _dataInfo;
while (_dataInfo.size()<40)
{
_dataInfo.append(" ");
cout << ' ';
}
cout << _ptr<< endl;
}
};
bool GreaterSort(Datainfo& Left,Datainfo& Right)
{
return Left._ptr < Right._ptr;
}
std::vector<Datainfo> StructDataInfo;
typedef void(*FUNC)();
void PrintVTable(int** &VTable)
{
std::cout << " 虚表函数地址: "<<VTable << std::endl;
for (int i = 0; (VTable[i]) != NULL; ++i)
{
__try
{
FUNC f = (FUNC)VTable[i];
f();
printf("<-第%d个虚函数地址: 0X%x,\n", i, VTable[i]);
}
__except (1)
{
std::cout << " 虚表函数结束 " << std::endl;
break;
}
}
std::cout << std::endl;
}
class Interface_PointC
{
public:
void PrintInterface_PointC()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointC _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _a is :";
NewData._ptr =(int**) &this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableC()
{
std::cout << "Interface_PointC的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
int _a = 0;
int _b = 0;
int _c = 0;
int _BaseData = 0;
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
private:
virtual void Interface_PointC_1() {
std::cout << " Interface_PointC::Interface_PointC_1 ";
}
virtual void Interface_PointC_2() {
std::cout << " Interface_PointC::Interface_PointC_2 ";
}
virtual void BaseFunctionA() {
std::cout << "Interface_PointC:: BaseFunctionA ";
};
virtual void BaseFunctionB() {
std::cout << "Interface_PointC:: BaseFunctionB ";
};
};
void PrintAllData()
{
std::cout << "输出所有" << endl;
std::sort(StructDataInfo.begin(), StructDataInfo.end(), GreaterSort);
for (auto var : StructDataInfo)
{
var.PrintSelf();
}
}
class Interface_PointA:virtual public Interface_PointC
{
public:
void PrintInterface_PointA()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointA Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
int _a = 0;
void PrintVPtrTableA()
{
std::cout << "Interface_PointA的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointA_1() {
std::cout << " Interface_PointA::Interface_PointA_1 ";
}
virtual void Interface_PointA_2() {
std::cout << "Interface_PointA:: Interface_PointA_2 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
virtual void BaseFunctionA() {
std::cout << "Interface_PointA:: BaseFunctionA ";
};
};
class Interface_PointB :virtual public Interface_PointC
{
public:
int _b = 0;
void PrintInterface_PointB()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointB Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableB()
{
std::cout << "Interface_PointB的虚表" << std::endl;
int** pVptrThird = (int**)(this) ;
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointB_1() {
std::cout << " Interface_PointB::Interface_PointB_1 ";
}
virtual void Interface_PointB_2() {
std::cout << " Interface_PointB::Interface_PointB_2 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointB:: BaseFunction ";
};
virtual void BaseFunctionB() {
std::cout << "Interface_PointB:: BaseFunctionB ";
};
};
//
class Point3D :public Interface_PointA,public Interface_PointB
{
public:
void PrintPoint3D()
{
Datainfo NewData;
NewData._dataInfo = "Point3D Start this is:";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_Point3Data is :";
NewData._ptr = (int**)&this->_Point3Data;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
PrintInterface_PointA();
PrintInterface_PointB();
PrintInterface_PointC();
}
void PrintVPtrTablePoint3D()
{
std::cout << "Point3D的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
virtual void Interface_PointB_1() {
std::cout << " Point3D::Interface_PointB_1 ";
}
virtual void Interface_PointA_1() {
std::cout << " Point3D::Interface_PointA_1 ";
}
void PrintVPtrTable()
{
PrintVPtrTableC();
PrintVPtrTableB();
PrintVPtrTableA();
PrintVPtrTablePoint3D();
}
virtual void Point3D_1() {
std::cout << " Point3D::Point3D_1 ";
}
virtual void Point3D_2() {
std::cout << "Point3D:: Point3D_2 ";
}
int _a = 0;
int _b = 0;
int _c = 0;
int _Point3Data = 0;
virtual void BaseFunction() override {
std::cout << " Point3D::BaseFunction ";
};
};
int main()
{
Point3D TestChildInstance = Point3D();
TestChildInstance.PrintPoint3D();
std::cout << "sizeof(void*) is " << sizeof(void*) << std::endl;
std::cout << "sizeof(int) is " << sizeof(int) << std::endl;
std::cout << "sizeof(Point3D) is " << sizeof(Point3D) << std::endl;
PrintAllData();
TestChildInstance.PrintVPtrTable();
return 0;
}
三个基类单虚继承且承菱形继承关系的情况:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Datainfo
{
int** _ptr;
string _dataInfo;
void PrintSelf()
{
cout << _dataInfo;
while (_dataInfo.size()<40)
{
_dataInfo.append(" ");
cout << ' ';
}
cout << _ptr<< endl;
}
};
bool GreaterSort(Datainfo& Left,Datainfo& Right)
{
return Left._ptr < Right._ptr;
}
std::vector<Datainfo> StructDataInfo;
typedef void(*FUNC)();
void PrintVTable(int** &VTable)
{
std::cout << " 虚表函数地址: "<<VTable << std::endl;
for (int i = 0; (VTable[i]) != NULL; ++i)
{
__try
{
FUNC f = (FUNC)VTable[i];
f();
printf("<-第%d个虚函数地址: 0X%x,\n", i, VTable[i]);
}
__except (1)
{
std::cout << " 虚表函数结束 " << std::endl;
break;
}
}
std::cout << std::endl;
}
class Interface_PointC
{
public:
void PrintInterface_PointC()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointC _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _a is :";
NewData._ptr =(int**) &this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableC()
{
std::cout << "Interface_PointC的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
int _a = 0;
int _b = 0;
int _c = 0;
int _BaseData = 0;
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
private:
virtual void Interface_PointC_1() {
std::cout << " Interface_PointC::Interface_PointC_1 ";
}
virtual void Interface_PointC_2() {
std::cout << " Interface_PointC::Interface_PointC_2 ";
}
virtual void BaseFunctionA() {
std::cout << "Interface_PointC:: BaseFunctionA ";
};
virtual void BaseFunctionB() {
std::cout << "Interface_PointC:: BaseFunctionB ";
};
};
void PrintAllData()
{
std::cout << "输出所有" << endl;
std::sort(StructDataInfo.begin(), StructDataInfo.end(), GreaterSort);
for (auto var : StructDataInfo)
{
var.PrintSelf();
}
}
class Interface_PointA:virtual public Interface_PointC
{
public:
void PrintInterface_PointA()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointA Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
int _a = 0;
void PrintVPtrTableA()
{
std::cout << "Interface_PointA的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointA_1() {
std::cout << " Interface_PointA::Interface_PointA_1 ";
}
virtual void Interface_PointA_2() {
std::cout << "Interface_PointA:: Interface_PointA_2 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
virtual void BaseFunctionA() {
std::cout << "Interface_PointA:: BaseFunctionA ";
};
};
class Interface_PointB :virtual public Interface_PointC
{
public:
int _b = 0;
void PrintInterface_PointB()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointB Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableB()
{
std::cout << "Interface_PointB的虚表" << std::endl;
int** pVptrThird = (int**)(this) ;
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointB_1() {
std::cout << " Interface_PointB::Interface_PointB_1 ";
}
virtual void Interface_PointB_2() {
std::cout << " Interface_PointB::Interface_PointB_2 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointB:: BaseFunction ";
};
virtual void BaseFunctionB() {
std::cout << "Interface_PointB:: BaseFunctionB ";
};
};
//
class Point3D :virtual public Interface_PointA,public Interface_PointB
{
public:
void PrintPoint3D()
{
Datainfo NewData;
NewData._dataInfo = "Point3D Start this is:";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_Point3Data is :";
NewData._ptr = (int**)&this->_Point3Data;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
PrintInterface_PointA();
PrintInterface_PointB();
PrintInterface_PointC();
}
void PrintVPtrTablePoint3D()
{
std::cout << "Point3D的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
virtual void Interface_PointB_1() {
std::cout << " Point3D::Interface_PointB_1 ";
}
virtual void Interface_PointA_1() {
std::cout << " Point3D::Interface_PointA_1 ";
}
void PrintVPtrTable()
{
PrintVPtrTableC();
PrintVPtrTableB();
PrintVPtrTableA();
PrintVPtrTablePoint3D();
}
virtual void Point3D_1() {
std::cout << " Point3D::Point3D_1 ";
}
virtual void Point3D_2() {
std::cout << "Point3D:: Point3D_2 ";
}
int _a = 0;
int _b = 0;
int _c = 0;
int _Point3Data = 0;
virtual void BaseFunction() override {
std::cout << " Point3D::BaseFunction ";
};
};
int main()
{
Point3D TestChildInstance = Point3D();
TestChildInstance.PrintPoint3D();
std::cout << "sizeof(void*) is " << sizeof(void*) << std::endl;
std::cout << "sizeof(int) is " << sizeof(int) << std::endl;
std::cout << "sizeof(Point3D) is " << sizeof(Point3D) << std::endl;
PrintAllData();
TestChildInstance.PrintVPtrTable();
return 0;
}
三个基类全虚继承且承菱形继承关系的情况:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Datainfo
{
int** _ptr;
string _dataInfo;
void PrintSelf()
{
cout << _dataInfo;
while (_dataInfo.size()<40)
{
_dataInfo.append(" ");
cout << ' ';
}
cout << _ptr<< endl;
}
};
bool GreaterSort(Datainfo& Left,Datainfo& Right)
{
return Left._ptr < Right._ptr;
}
std::vector<Datainfo> StructDataInfo;
typedef void(*FUNC)();
void PrintVTable(int** &VTable)
{
std::cout << " 虚表函数地址: "<<VTable << std::endl;
for (int i = 0; (VTable[i]) != NULL; ++i)
{
__try
{
FUNC f = (FUNC)VTable[i];
f();
printf("<-第%d个虚函数地址: 0X%x,\n", i, VTable[i]);
}
__except (1)
{
std::cout << " 虚表函数结束 " << std::endl;
break;
}
}
std::cout << std::endl;
}
class Interface_PointC
{
public:
void PrintInterface_PointC()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointC _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _a is :";
NewData._ptr =(int**) &this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointC _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableC()
{
std::cout << "Interface_PointC的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
int _a = 0;
int _b = 0;
int _c = 0;
int _BaseData = 0;
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
private:
virtual void Interface_PointC_1() {
std::cout << " Interface_PointC::Interface_PointC_1 ";
}
virtual void Interface_PointC_2() {
std::cout << " Interface_PointC::Interface_PointC_2 ";
}
virtual void BaseFunctionA() {
std::cout << "Interface_PointC:: BaseFunctionA ";
};
virtual void BaseFunctionB() {
std::cout << "Interface_PointC:: BaseFunctionB ";
};
};
void PrintAllData()
{
std::cout << "输出所有" << endl;
std::sort(StructDataInfo.begin(), StructDataInfo.end(), GreaterSort);
for (auto var : StructDataInfo)
{
var.PrintSelf();
}
}
class Interface_PointA:virtual public Interface_PointC
{
public:
void PrintInterface_PointA()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointA Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointA _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
int _a = 0;
void PrintVPtrTableA()
{
std::cout << "Interface_PointA的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointA_1() {
std::cout << " Interface_PointA::Interface_PointA_1 ";
}
virtual void Interface_PointA_2() {
std::cout << "Interface_PointA:: Interface_PointA_2 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointA:: BaseFunction ";
};
virtual void BaseFunctionA() {
std::cout << "Interface_PointA:: BaseFunctionA ";
};
};
class Interface_PointB :virtual public Interface_PointC
{
public:
int _b = 0;
void PrintInterface_PointB()
{
Datainfo NewData;
NewData._dataInfo = "Interface_PointB Start this is :";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Interface_PointB _BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
}
void PrintVPtrTableB()
{
std::cout << "Interface_PointB的虚表" << std::endl;
int** pVptrThird = (int**)(this) ;
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
private:
virtual void Interface_PointB_1() {
std::cout << " Interface_PointB::Interface_PointB_1 ";
}
virtual void Interface_PointB_2() {
std::cout << " Interface_PointB::Interface_PointB_2 ";
}
virtual void BaseFunction() {
std::cout << "Interface_PointB:: BaseFunction ";
};
virtual void BaseFunctionB() {
std::cout << "Interface_PointB:: BaseFunctionB ";
};
};
//
class Point3D :virtual public Interface_PointA,virtual public Interface_PointB
{
public:
void PrintPoint3D()
{
Datainfo NewData;
NewData._dataInfo = "Point3D Start this is:";
NewData._ptr = (int**)this;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_a is :";
NewData._ptr = (int**)&this->_a;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_b is :";
NewData._ptr = (int**)&this->_b;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_c is :";
NewData._ptr = (int**)&this->_c;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_Point3Data is :";
NewData._ptr = (int**)&this->_Point3Data;
StructDataInfo.push_back(NewData);
NewData._dataInfo = "Point3D Child &_BaseData is :";
NewData._ptr = (int**)&this->_BaseData;
StructDataInfo.push_back(NewData);
PrintInterface_PointA();
PrintInterface_PointB();
PrintInterface_PointC();
}
void PrintVPtrTablePoint3D()
{
std::cout << "Point3D的虚表" << std::endl;
int** pVptrThird = (int**)(this);
int** pVptrThirdResult = (int**)(pVptrThird[0]);
PrintVTable(pVptrThirdResult);
}
virtual void Interface_PointB_1() {
std::cout << " Point3D::Interface_PointB_1 ";
}
virtual void Interface_PointA_1() {
std::cout << " Point3D::Interface_PointA_1 ";
}
void PrintVPtrTable()
{
PrintVPtrTableC();
PrintVPtrTableB();
PrintVPtrTableA();
PrintVPtrTablePoint3D();
}
virtual void Point3D_1() {
std::cout << " Point3D::Point3D_1 ";
}
virtual void Point3D_2() {
std::cout << "Point3D:: Point3D_2 ";
}
int _a = 0;
int _b = 0;
int _c = 0;
int _Point3Data = 0;
virtual void BaseFunction() override {
std::cout << " Point3D::BaseFunction ";
};
};
int main()
{
Point3D TestChildInstance = Point3D();
//GetVPtrTableAddress(&TestChildInstance);
TestChildInstance.PrintPoint3D();
std::cout << "sizeof(void*) is " << sizeof(void*) << std::endl;
std::cout << "sizeof(int) is " << sizeof(int) << std::endl;
std::cout << "sizeof(Point3D) is " << sizeof(Point3D) << std::endl;
//std::cout << std::endl;
PrintAllData();
TestChildInstance.PrintVPtrTable();
//
return 0;
}
结语:
情况还是挺复杂,以上结论是根据结果反推验证而得,看到本文者可自行用本文提供例子进行反推。