class AA{public: virtual void fun1() { cout << "AA::fun1()" << endl; }public: int _aa;};class BB :public AA{public: virtual void fun1() { cout << "BB::fun1()" << endl; }public: int _bb;};class CC :public AA{public: virtual void fun1() { cout << "CC::fun1()" << endl; }public: int _cc;};class DD :public BB, public CC{public: virtual void fun1() { cout << "DD::fun1()" << endl; }public: int _dd;};int main(){ DD d; d.BB::_aa = 1; d.CC::_aa = 2; d._bb = 3; d._cc = 4; d._dd = 5;cout << sizeof(d) << endl; system("pause"); return 0;}前面也提到過,菱形繼承會存在數據的冗余和二義性。那如果加上虛函數結果會怎樣呢?我們知道有虛表指針存放虛函數的地址;我們再從內存的角度觀察一下:
觀察結果:

我們畫出菱形的對象模型如下:

現在我們再來分析內存為什么是28個字節,BB對象中有一個虛表指針_vfptr存放重寫派生類DD::fun1()虛函數的地址,BB的對象中還有從派生類AA繼承的整形_aa和自己類中的_bb;CC的對象中有一個虛表指針_vfptr 重寫了派生類DD::fun1()的虛函數的地址,以及自己從基類集成的_aa;DD的對象中只有自己類中的_dd。這樣我們就很容易搞明白28個字節的原因了。
二.菱形虛繼承(虛函數的重寫)
#include<iostream>using namespace std;class AA{public: virtual void fun1() { cout << "AA::fun1()" << endl; }public: int _aa;};class BB :virtual public AA{public: virtual void fun1() { cout << "BB::fun1()" << endl; } virtual void fun2() { cout << "BB::fun2()" << endl; }public: int _bb;};class CC :virtual public AA{public: virtual void fun1() { cout << "CC::fun1()" << endl; } virtual void fun2() { cout << "CC::fun2()" << endl; }public: int _cc;};class DD :public BB, public CC{public: virtual void fun1() { cout << "DD::fun1()" << endl; } virtual void fun2() { cout << "DD::fun2()"<< endl; }public: int _dd;};int main(){ DD d; d.BB::_aa = 1; d.CC::_aa = 2; d._bb = 3; d._cc = 4; d._dd = 5; cout << sizeof(d) << endl; system("pause"); return 0;}
但是結果是36,我們再從監視窗口來看,
我們看到有兩個虛表指針,有兩層意思,第一層派生類的虛函數BB::fun2()重寫了基類的虛函數AA::fun2().,第二層派生類DD::fun2()有重寫了虛函數BB::fun2()。我們再畫出菱形對象的模型如下:
來分析內存的大小為什么是36,對象BB我們可以理解有三部分組成,一個虛表指針存放虛函數DD::fun2()的地址,一個虛基址指針用來存放BB對象的偏移量,整型_bb對象CC也有三部分組成,一個虛表指針存放虛函數DD::fun2()的地址,一個 虛基表指針存放CC對象的偏移量,以及整形_cc。對象DD只有整形_dd,對象AA有兩部分虛表指針和整形_aa.三.總結
虛函數的作用:虛函數的重寫是實現多態的條件,通過虛表指針調用相應的函數實現。虛繼承的作用:1.解決菱形繼承的二義性和數據冗余的問題,2.底層實現原理與編譯器相關,一般通過虛基類 指針實現,即各對象中只保存一份父類的對象,多繼承時通過虛基類指針引用該公共對象,從而避 免菱形繼承中的二義性問題。對象模型前面也有介紹http://blog.csdn.net/f2016913/article/details/55292948以及菱形繼承http://blog.csdn.net/f2016913/article/details/55225939
|
新聞熱點
疑難解答