C 多型 虛函式 虛析構函式以及虛函式表

2021-08-20 14:37:13 字數 1927 閱讀 9022

什麼是多型:

指不同物件收到相同訊息時或相同物件收到不同訊息時產生不同的動作。

這裡先說下為什麼會用到虛函式:

以下面的程式為例:

這個程式中,carp是fish的繼承類,而carp中覆蓋了swim這個方法,在makefishswim這個函式中,要使用fish類的形參,而你將yourfish這個carp類的實參傳遞給了這個函式,讓他執行swim這個函式,這會發生什麼,上面的程式執行結果:

這說明了什麼?說明在makefishswim這個程式中,它定義它的形參是fish型別的,雖然你將yourfish這個carp類傳到了它那裡,它仍然認為yourfish是fish類的,並呼叫了fish類swim。

顯然我們的初衷並不是這樣,是希望對應的類執行自己的方法,那怎麼避免這種情況呢?這就需要虛函式了。

虛函式的定義很簡單,直接在父類方法定義最前面加上關鍵字「virtual」即可!在父類這個函式前一定得加virtual,子類的話,可以不加,系統編譯時候會幫忙加,不過加上是好習慣。

舉例:

虛析構函式:

當我以父類指標指向乙個子類時候,比如我這樣寫:  fish  *fish1  = new carp;這樣寫是可行的!如果我沒有把fish類的析構函式用virtual修飾,那麼在main中呼叫析構函式時,也就是我寫  delete fish,只會呼叫父類的析構函式,而不會呼叫子類/carp的析構函式!

當然如果一開始就建立的是子類的指標,最後銷毀這個指標時,即使沒有virtual修飾,也會把父類子類的析構函式都呼叫!

綜上,虛函式的另一大重要作用在於,在使用父類指標指向子類的情況中,對於父類析構函式,如果沒有virtual修飾,delete將不會作用到子類中的析構函式,會造成資源未釋放,記憶體洩漏等隱患。

virtual 限制:

1. virtual不能修飾全域性函式,必須是某個類的函式成員

2. virtual 不能修飾靜態成員函式

3. virtual不能修飾內聯函式

4. virtual不能修飾建構函式

注意:如果乙個類,本意就不會被繼承,那麼請不要用vitual修飾它的成員函式,因為這樣會造成記憶體的浪費:任何帶有虛函式的類,會自動建立乙個虛函式表指標,在32位系統中,佔4個位元組,這可是實打實的記憶體啊,不需要的話,千萬別定義虛函式。

實現原理:

在父類中 ,只要我們有虛函式成員,系統就會給他建立乙個成員:虛函式表指標,注意,是個指標,指向虛函式表,虛函式表中存放的都是,這個父類建立的虛函式的入口位址,這個位址指向相應的虛函式。

對於它的子類來說,如果它沒有建立自己的虛函式,它繼承了父類以後,會建立自己的虛函式指標,注意,這裡的虛函式指標值與父類是不同的,也就是說它的虛函式表首位址不同,而虛函式表裡指向的虛函式入口位址與父類的虛函式入口位址一樣!因為它沒有建立自己的虛函式!

如果它建立了自己的虛函式,那麼它的虛函式表裡對於的虛函式首位址就不同了,就指向了它自己建立的虛函式!

建立了自己的虛函式後:

C 中虛函式,純虛函式以及多型

關於建構函式和析構函式 在整理排序演算法的時候想到可以藉此熟悉一下類的構造以及繼承等知識點,就寫了乙個排序基類宣告乙個排序函式,然後寫多個排序演算法的子類重寫這個排序函式,過程中順便研究了一下virtual和多型的概念。首先回顧一下虛函式和純虛函式的八股文,虛函式是多型的實現機制,宣告乙個虛函式就是...

C 虛函式,純虛函式,虛析構和純虛析構

c 虛函式 定義為虛函式是為了允許用基類的指標來呼叫子類的這個函式,是需要具體實現的 virtual void funtion1 c 純虛函式 一 定義 純虛函式是在基類中宣告的虛函式,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛函式的方法是在函式原型後加 0 vir...

C 虛析構函式 純虛析構函式

虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...