C++虚继承中的对象内存布局

来源:互联网 发布:windows更新消失 编辑:程序博客网 时间:2024/05/21 09:23

钻石型虚拟继承

虚继承是为了解决多继承中的数据冗余而出现的。

eg:

wKioL1bgC5DDO7E6AAAh_Ka19tA339.png

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>using namespace std;typedef void(*FUNC)();class Base{public:virtual void fun1(){cout << "Base::fun1()" << endl;}public:int _b;};class Parent1:virtual public Base{public:virtual void fun1(){cout << "Parent1::fun1()" << endl;}virtual void fun2(){cout << "Parent1::fun2()" << endl;}public:int _p1;};class Parent2 :virtual public Base{public:virtual void fun1(){cout << "Parent2::fun1()" << endl;}virtual void fun3(){cout << "Parent2::fun3()" << endl;}public:int _p2;};class Child : public Parent1,public Parent2{public:virtual void fun1(){cout << "Child::fun1()" << endl;}virtual void fun2(){cout << "Child::fun2()" << endl;}virtual void fun3(){cout << "Child::fun3()" << endl;}virtual void fun4(){cout << "Child::fun4()" << endl;}public:int _c;};void PrintVfptr(int* vptr)//打印虚函数表{cout << "虚函数表: " << vptr << endl;for (int i = 0; vptr[i] != 0; ++i){printf("第%d个虚函数:%p  >> ", i, vptr[i]);FUNC f = (FUNC)(vptr[i]);f();}}void PrintfMove(int* vbptr)//打印偏移量{cout << "偏移量 >: " << endl;for (int i = 0; vbptr[i] != 0; ++i){printf("第%d个虚函数:%d\n", i, vbptr[i]);}cout << endl;}void Test(){Child c;c._b = 1;c._p1 = 2;c._p2 = 3;c._c = 4;cout << "sizeof(Base)::" << sizeof(Base) << endl;cout << "sizeof(Parent1)::" << sizeof(Parent1) << endl;cout << "sizeof(Parent2)::" << sizeof(Parent2) << endl;cout << "sizeof(Child)::" << sizeof(Child) << endl;int* cAddress = (int*)&c;cout << "Parent1::";int* tmpP1 = (int*)(*cAddress);PrintVfptr(tmpP1);cout << "Parent1::";int* moveP1 = (int*)(*(cAddress + 1));PrintfMove(moveP1);cout << endl;cout << "Parent2::";int* tmpP2 = (int*)(*(cAddress + 3));PrintVfptr(tmpP2);cout << endl;cout << "Parent1::";int* moveP2 = (int*)(*(cAddress + 4));PrintfMove(moveP2);cout << endl;int* tmpBase = (int*)(*(cAddress + 7));PrintVfptr(tmpBase);cout << endl;}int main(){Test();system("pause");return 0;}

程序运行结果:

wKioL1bgDP3SDYtoAABJX8XjyvM116.png

对象在内存中的布局:

wKioL1bgEP7jOSsDAACAD7wYuSc836.png大家可以发现:

0x0014F8F8 + 0xFFFFFFFC(-4) = 0x0014F8F4, 0x0014F8F8 + 0x00000018 = 0x0014F910; 

0x0014F904 + 0xFFFFFFFC(-4) = 0x0014F900, 0x0014F904 + 0x0000000c = 0x0014F910.

所以,有以下结论:

   在虚继承时,类中会自动加一个指针(VBPTR),该变量指向一个全类共享的偏移量表,如果本类有虚函数,那么第一项记录着当前子对象相对与虚基类表指针(VBPTR指针)的偏移,是FF FF FF FC(也就是-4),如果没有则是零;第二项起是被继承的基类(上述例子为Base类)子对象相对于VBPTR指针的偏移量。

0 0
原创粉丝点击