关于C++对象继承中的内存布局示例详解
|
掌握了单继承和多继承的规律,按照总结的一步步分析,就可以最终得到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放在最末端,并在子类中存放一个虚基表,方便找到父类;而虚基表的前四个字节存放的是对于自己虚函数表的偏移量,再往下四个字节才是对于父类的偏移量。 2)接下来就抽象出来分析模型
总结 1)虚函数按照其声明顺序放于表中; 2)父类的虚函数在子类的虚函数前面(由于子类单继承父类,直接使用父类的虚函数表); 3)覆盖的func()函数被放到了虚表中原来父类虚函数的位置; 4)没有被覆盖的函数依旧; 5)如果B,C虚继承A,并且B,C内部没有再声明或定义虚函数,则B,C没有对应的虚函数表; 6)在菱形的虚拟继承中,要注意A为B,C所共有的,在打印对应虚函数表时要注意偏移量。 好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。 (编辑:清远站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |





