C 多型,虛函式小結

2021-08-08 07:45:49 字數 2057 閱讀 5585

之前學c++的時候, 課上的特別快。 很多東西當時只是會用,細節以及理解都很不到位。 時隔一年是時候重新回顧一下了。 不然之後都不好意思說自己學過c++… :)

這個僅供自己回顧使用。把自己的費解易錯地方記錄下來。

首先就是多型。 把一些我認為的理解要點記錄一下:

1.什麼是多型

從行為(效果)上看, 多型即使相同的執行**(或者呼叫方式)因引數傳入不同(可以是引數型別, 也可以是引數個數,也可以只是引數的記憶體實體不同),而產生不同效果(實際呼叫了不同函式)。

針對虛函式的是動態多型性。其更加具體的效果是: 用幾乎完全相同(引數型別, 個數相同)的呼叫方式, 達到不同的呼叫效果。

2. 多型的常見用法。

用法必然能體現其優點。 大體而言, 下面這個例子可以說明乙個常見的情況:

class base 

};class inherit : public base

};class caller

};int main()

考慮這段**與具體實際的聯絡。在實際中,base 可能是乙個封裝好的類庫, 不能夠修改內部**, 但是我們可以對其進行拓展, 就比如這裡的inherit 類。

而caller類事實上已經可能被另乙個類庫封裝住了。我們也無法修改。換言之,我們不能夠修改呼叫的任何**, 卻要讓程式根據傳入的不同物件執行不同操作。

相比較而言,不用動態多型時對型別的解析是個很大的問題。 固然我們(有可能)可以預先寫好,但是我們不可能預先知道所有情況(即我們之後可能拓展的型別) 。基於此, 在寫諸如caller這種類庫時,其中的call函式必定傳入的引數型別是基類型別。這樣再結合虛函式的動態繫結, 可以在保證類庫對新型別很好的相容情況下, 還不用修改已有的**。

3. 多型比起函式過載以及函式重定義的優勢

多型和函式過載並不矛盾, 甚至可以說某種程度的互補。 函式過載要求函式名相同但是函式引數型別或個數不同。 而子類虛函式要求函式引數必須和基類完全相同。 兩者互不影響。

函式重定義來講, 上文有提到。 因為caller類不可能知道使用者自定義的型別, 所以只能用基類來呼叫。而對於函式重定義, 就是「傳入什麼型別的引數我就只呼叫其靜態型別所對應的同名函式」。這樣顯然就無法支援使用者自定義的拓展型別了。

簡單說來, 虛函式表幹的是這樣一件事情: 首先, 為擁有虛函式的類建立(乙個或多個, 若是繼承鏈上存在多繼承,則可能多個虛函式表)虛函式表。在該類例項化的時候, 為每個物件分配乙個虛函式指標, 指向該虛函式表。 虛函式指標放在類所在記憶體的起始位址處。虛函式表建立之時, 首先複製乙份其父類的虛函式表(所以多繼承會有多個), 然後檢查自己的類的方法中有沒有虛函式覆蓋了原先的父類的虛函式(我的理解是通過檢查函式簽名來檢查函式是否相同),若有的話把原先虛函式表中指向父類虛函式的位址改為指向自己的那個函式的位址即可。若是存在之前沒有在父類虛函式表出現過的虛函式,則在自己的虛函式表中新增一項,並指向自己的這個虛函式。(處於需要增添項來考慮, 個人認為虛函式表在記憶體不是連續排列,而應該是像鍊錶那樣做的)

多繼承下具有多個虛函式表, 那麼假設子類沒有虛函式覆蓋任何父類的,而不同父類間存在同名(相同函式簽名)的虛函式, 這時候利用父類指標來呼叫這個名稱的虛函式, 具體呼叫哪個,就要看父類指標的型別了:呼叫與父類指標的類中的那個函式。

更加具體參考:

總結一下: 判斷虛函式呼叫的方法。

根據父類指標找到子類中相應的虛函式表。(單繼承下表唯一)

判斷該虛函式表中該函式名稱(簽名)對應的函式是否被子類中虛函式覆蓋。

若沒被覆蓋, 呼叫父類指標對應類中的函式, 若被覆蓋, 呼叫子類中的對應虛函式。

繼承 虛函式和多型小結

一.知識點總結 繼承 1.定義 在已有類的基礎上建立新類的過程。乙個 b 類繼承 a類,或稱從類 a 派生類 b類 a 稱為基類 父類 類 b 稱為派生類 子類 2.類繼承關係的語法形式 class 派生類名 基類名錶 資料成員和成員函式宣告 基類名錶 構成訪問控制 基類名1,訪問控制 基類名 2 ...

C 多型,虛函式

在c 中可以用基類指標指向其派生類,如果乙個派生類繼承多個父類,那麼如何通過基類指標訪問同名的成員呢?如果基類a,基類b中都有函式fun 派生類在同時繼承a b後在記憶體中根據繼承的順序分配記憶體,例如在繼承列表中出現的是b,a,那麼b中的成員在a的之前,當我們用b的指標去訪問時候,編譯器便將指標指...

C 虛函式多型

由虛函式實現的動態多型性就是 同一類族中不同類的物件,對同一函式呼叫作出不同的響應。虛函式的使用方法是 1 在基類用virtual宣告成員函式為虛函式。這樣就可以在派生類中重新定義此函式,為它賦予新的功能,並能方便地被呼叫。在類外定義虛函式時,不必再加virtual。2 在派生類中重新定義此函式,要...