在之前的部落格中有簡單的介紹了一下:沒有虛函式的菱形繼承。此篇部落格將對菱形繼承進行公升級,介紹有虛函式的菱形繼承。
舉乙個簡單的例子:
#includeusing namespace std;
class aa
virtual void fun2()
virtual void fun3()
protected:
int _aa;
};class bb : public aa
virtual void fun2()
protected:
int _bb;
};class cc : public aa
virtual void fun2()
protected:
int _cc;
};class dd : public bb, public cc
virtual void fun2()
virtual void fun4()
protected:
int _dd;
};typedef void (*func)();
void printvtable(int* vtable)
}int main()
監視視窗能夠看出菱形繼承裡面的記憶體布局如下:
通過監視視窗我們能夠看到dd中有繼承的類bb和類cc,其中bb和cc中都各自包括乙個虛表指標,且指標的位址不相同,則兩個類各自存在乙個虛函式表。同時我們也能夠看到菱形繼承中,dd中存在兩個成員_aa,這就存在問題,當我們想要訪問_aa時,編譯器不知道我們想要訪問的是哪乙個變數,這就說明菱形繼承存在二義性和資料冗餘。那麼如何解決菱形繼承所存在的問題呢?
菱形虛擬繼承解決了菱形繼承中存在的二義性和資料冗餘。虛擬繼承就是增加虛基表和偏移量,將bb和cc繼承改為虛擬繼承。
**如下:
#includeusing namespace std;
class aa
virtual void fun2()
virtual void fun3()
protected:
int _aa;
};class bb : virtual public aa
virtual void fun2()
protected:
int _bb;
};class cc : virtual public aa
virtual void fun2()
protected:
int _cc;
};class dd : virtual public bb, virtual public cc
virtual void fun2()
virtual void fun4()
protected:
int _dd;
};typedef void (*func)();
void printvtable(int* vtable)
}int main()
通過監視視窗,我們可以看到以下現象:
菱形虛擬繼承比菱形繼承的dd中多存在乙個指標_vfptr,該指標指向偏移量。至此,菱形繼承消除了其存在的二義性及資料冗餘。
菱形繼承和菱形虛繼承
繼承是c 的一大特點,我們通過菱形繼承和菱形虛繼承對繼承進行進一步的分析。菱形繼承 建立乙個基類a讓b1和b2公有繼承於它,讓c公有繼承b1和b2。class a a int a class b1 public a b1 int b1 class b2 public a b2 int b2 clas...
帶有虛函式的菱形繼承和帶有虛函式的菱形虛繼承
對於某些函式來說,基類希望它的派生類定義適合自身的版本,此時基類就將這些函式宣告為虛函式。在存在虛函的類,建立物件時會產生虛表指標,虛表指標指向乙個虛表,這時就可以通過虛表訪問自己定義的函式。通過下面兩種繼承進行分析 帶有虛函式的菱形繼承 以下圖的模型為例進行分析 我們觀察c類物件在記憶體中的結構 ...
菱形繼承的虛函式表
虛函式 類的成員函式前面加virtual 虛函式的主要作用就是實現多型 那麼多型 顧名思義就是一種事物的多種形態。c 中,指具有不同功能的函式可以用同乙個函式名,這樣可以用乙個函式名呼叫不同內容的函式。虛函式表 虛表 通過一片連續的位址來儲存虛函式的位址 菱形繼承舉例 說明 若子類中有虛函式,而所繼...