帶有虛函式的菱形繼承和帶有虛函式的菱形虛繼承

2021-07-30 11:13:01 字數 2400 閱讀 1550

對於某些函式來說,基類希望它的派生類定義適合自身的版本,此時基類就將這些函式宣告為虛函式

在存在虛函的類,建立物件時會產生虛表指標,虛表指標指向乙個虛表,這時就可以通過虛表訪問自己定義的函式。

通過下面兩種繼承進行分析:

【帶有虛函式的菱形繼承】

以下圖的模型為例進行分析:

};我們觀察c類物件在記憶體中的結構:

當發生繼承時,如果派生類重寫了基類的虛函式,那麼派生類的物件中會修改基類的虛表,虛表中的函式指標會指向派生類自己重寫的函式,如果派生類沒有重寫基類的虛函式,那麼派生類不會改變那個虛函式的指向只是把它繼承下來。

通過上圖發現,b1類的虛表指標中add()函式被替換為c類的add()函式指標,b2類的虛表指標中add()函式也被替換為c類的add()函式指標,但是卻發現這兩個指標不相同,這可以說明兩個函式不是同乙個函式麼?這是不可以的!通過上圖發現,所說的函式指標其實指向的是一條跳轉語句,在跳轉之後會做一些修正最後使他們訪問的是同乙個函式。

在發生動態繫結時,執行的過程:

【帶有虛函式的菱形虛擬繼承】

對於菱形虛擬繼承我們知道,派生類在繼承時加上virtual關鍵字就說明,它可以共享它的基類,當多個派生類都虛繼承乙個基類,並且有其他的類繼承於派生類,那麼在派生類的子類的物件中只會有乙份基類的成員,在每個派生類成員中都會有乙個指標指向一塊空間,空間裡面存放了派生類相對於自己的偏移量和相對於基類的偏移量。

我們同通過例項來進一步研究(以下圖的模型為例):

【帶有虛函式的菱形虛擬繼承】

對於菱形虛擬繼承我們知道,派生類在繼承時加上virtual關鍵字就說明,它可以共享它的基類,當多個派生類都虛繼承乙個基類,並且有其他的類繼承於派生類,那麼在派生類的子類的物件中只會有乙份基類的成員,在每個派生類成員中都會有乙個指標指向一塊空間,空間裡面存放了派生類相對於自己的偏移量和相對於基類的偏移量。

我們同通過例項來進一步研究(以下圖的模型為例):

};我們觀察c類物件在記憶體中的結構:

總結:

當乙個類有虛函式時,在其物件的開始會生成乙個虛表指標,指向的虛表中會存放虛函式的位址。

當乙個派生類繼承乙個帶有虛函式的基類時,派生類物件成員中基類部分中的虛表指標會被派生類所修改,成為派生類自己的虛表指標。在虛表中,如果虛函式在派生類中被重寫那麼就會存放被重寫過的虛函式指標,如果沒有重寫基類的虛函式,就會單純的繼承下來存放基類的虛函式指標。

當乙個派生類繼承多個帶有虛函式的基類時,派生類物件成員中基類部分中的虛表指標會被派生類所修改,成為派生類自己的虛表指標(相當於派生類自己有多個虛表指標)。如果重寫了某個基類的虛函式,那麼對應的去修改繼承於這個基類的成員中的虛表,使指標指向派生類重寫過得虛函式,如果沒有重寫就單純的繼承。

菱形繼承和菱形虛繼承

繼承是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...

菱形繼承和虛繼承

1.菱形繼承 菱形繼承概念圖 菱形繼承物件模型 參照菱形繼承物件模型,不難發現若呼叫dd類時,裡面包含兩個相同的aa類的所有成員,在呼叫過程中會出現二義性和資料冗餘的問題,為了解決上述問題,我們提出了虛繼承。接下來通過簡單例項 講解虛函式及底層實現。樣例 include using namespac...

虛擬繼承 虛函式,含有虛函式的菱形虛擬繼承

一 虛擬繼承 虛函式 場景 派生類沒有自己的虛函式,只是繼承基類的虛函式 我們看乙個例子 class base virtual void funtest2 int b class derived virtual public base virtual void funtest2 int d type...