下面用一段菱形繼承的代碼來探究菱形繼承的對象模型
class AA{public: virtual void fun1() { cout << "AA::fun1()" << endl; }public: int _a;};class BB : public AA{public: virtual void fun1() { cout << "BB::fun1()" << endl; }public: int _b;};class CC : public AA{public: virtual void fun1() { cout << "CC::fun1()" << endl; }public: int _c;};class DD :public BB,public CC{public: virtual void fun1() { cout << "DD::fun1()" << endl; } virtual void fun2() { cout << "DD::fun2()" << endl; }public: int _d;};void Test1(){ DD d; d.BB::_a = 1; d.CC::_a = 2; d._b = 3; d._c = 4; d._d = 5;}打開內存窗口,進行單步調試,結果如下:
對于對象d,重寫了fun1(),所以將DD的fun1()放入虛表,再將fun2()放入虛表,圖片中另一個虛表指針指向的是CC中的虛函數,CC中的fun1()重寫了AA中的fun1(),所以在虛表中放入CC的fun1()。這一這樣理解,橙色區域本來應給是AA類,續表中存儲的是AA::fun1()的地址,但是BB類中從寫了fun1(),所以把AA::fun1()替換為了CC::fun1()。所以,對于一個類中的虛函數,若是重寫的父類的,則將虛表中的函數地址替換為自己的虛函數地址,若不是重寫的函數,則直接將該函數地址放入虛表中。
現在把上面的代碼改為虛擬繼承,再來看內存窗口中的結果:
下面提供完整的代碼調用虛函數

新聞熱點
疑難解答