关于C++对象继承中的内存布局示例详解
发布时间:2020-12-31 00:30:32 所属栏目:创业 来源:网络整理
导读:副标题#e# 前言 本文给大家介绍的是关于C++对象继承的内存布局的相关内容,分享出来供大家参考学习,在开始之前说明下,关于单继承和多继承的简单概念可参考此文章 以下编译环境均为:WIN32+VS2015 虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Funct
|
掌握了单继承和多继承的规律,按照总结的一步步分析,就可以最终得到D的虚函数表。
由于子类B继承父类A,所以B与A公用一个虚函数表,又因为B是D多继承中的第一个继承的类,所以B,D共用一个虚函数表。 菱形的虚拟继承(成员变量 + 虚函数覆盖) 参考下面这个例子:
class A
{
public:
virtual void func1()
{
cout << "A::func1()" << endl;
}
virtual void func2()
{
cout << "A::func2()" << endl;
}
public:
int _a;
};
class B : virtual public A//虚继承A,覆盖func1()
{
public:
virtual void func1()
{
cout << "B::func1()" << endl;
}
virtual void func3()
{
cout << "B::func3()" << endl;
}
public:
int _b;
};
class C : virtual public A //虚继承A,覆盖func1()
{
virtual void func1()
{
cout << "C::func1()" << endl;
}
virtual void func3()
{
cout << "C::func3()" << endl;
}
public:
int _c;
};
class D : public B,public C//虚继承B,C,覆盖func1()
{
virtual void func1()
{
cout << "D::func1()" << endl;
}
virtual void func4()
{
cout << "D::func4()" << endl;
}
public:
int _d;
};
typedef void(*FUNC) ();
void PrintVTable(int* VTable)
{
cout << " 虚表地址>" << VTable << endl;
for (int i = 0; VTable[i] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout << endl;
}
void Test1()
{
D d;
d.B::_a = 1;
d.C::_a = 2;
d._b = 3;
d._c = 4;
d._d = 5;
cout <<"sizeof(A) = "<< sizeof(A) << endl;
cout << "sizeof(B) = " << sizeof(B) << endl;
cout << "sizeof(C) = " << sizeof(C) << endl;
//打印d的虚函数表
int* VTable = (int*)(*(int*)&d);
PrintVTable(VTable);
//打印C的虚函数表
VTable = (int*)*(int*)((char*)&d + sizeof(B)-sizeof(A));
PrintVTable(VTable);
//打印A的虚函数表
VTable = (int*)*(int*)((char*)&d + sizeof(B)+sizeof(C)-2*sizeof(A)+4);
PrintVTable(VTable);
}
接下来就慢慢分析: 1)先通过调试查看内存中是如何分配的,并和我们打印出的虚函数表对应起来:
注:由于B,C是虚继承A,所以编译器为了解决菱形继承所带来的“二义性”以及“数据冗余”,便将A放在最末端,并在子类中存放一个虚基表,方便找到父类;而虚基表的前四个字节存放的是对于自己虚函数表的偏移量,再往下四个字节才是对于父类的偏移量。 (编辑:网站开发网_盐城站长网 ) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐
热点阅读



