鑽石型虛擬繼承
ios
虛繼承是爲了解決多繼承中的數據冗餘而出現的。
ide
eg:函數
#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; }
程序運行結果:佈局
對象在內存中的佈局:spa
0x0014F8F8 + 0xFFFFFFFC(-4) = 0x0014F8F4, 0x0014F8F8 + 0x00000018 = 0x0014F910; 對象
0x0014F904 + 0xFFFFFFFC(-4) = 0x0014F900, 0x0014F904 + 0x0000000c = 0x0014F910.blog
因此,有如下結論:繼承
在虛繼承時,類中會自動加一個指針(VBPTR),該變量指向一個全類共享的偏移量表,若是本類有虛函數,那麼第一項記錄着當前子對象相對與虛基類表指針(VBPTR指針)的偏移,是FF FF FF FC(也就是-4),若是沒有則是零;第二項起是被繼承的基類(上述例子爲Base類)子對象相對於VBPTR指針的偏移量。內存