基類指標、虛純虛擬函式、多型性、虛析構

爱新觉罗LQ發表於2024-10-26

多型

基類指標

//  父類指標可以 new 一個子類物件
Human *pman = new Man();
Human *pwman = new Wonan();

丟擲問題:父類指標沒有辦法呼叫子類的成員函式,那麼你為什麼還讓父類指標 new 一個子類物件呢?
下面與虛擬函式搭配

虛擬函式(動態繫結)

我們只定義一個物件指標,就能夠呼叫父類,以及各個子類的同名函式? ===> 有,這個物件指標,它的型別必須是父類型別
對這個函式有要求:

  1. 父類中,函式宣告之前要加 virtual 宣告成虛擬函式
  2. 一旦某個函式(在基類)被宣告成了虛擬函式,那麼所有派生類(子類)中同名函式都是虛擬函式
Human *phuman = new Men();
phuman->eat();  //  呼叫的是 Men 類的 eat 函式
delete phuman;  //  new 的物件使用完之後要 delete,防止記憶體洩漏

phuman = new Women();
phuman->eat();  //  呼叫的是 Women 類的 eat 函式
delete phuman;

phuman = new Human();
phuman->eat();  //  呼叫的是 Human 類的 eat 函式
delete phuman;

override

注意:為了避免你在子類中寫錯虛擬函式,在 C++11 中,你可以在函式宣告這裡增加一個 override 關鍵字
這個關鍵字在 "子類" 中,而且是子虛擬函式專用

override就是用來說明派生類中的虛擬函式,你用了這個關鍵字之後,編譯器就會認為你這個 函式就是覆蓋了父類中的同名函式。
只有虛擬函式才存在子類可以覆蓋父類中同名函式的問題,那麼編譯器就會在父類中找同名同參的虛擬函式,如果沒找到,編譯器就會報錯、

final

final 也是虛擬函式專用,是用在父類,如果我們在父類的函式宣告中加了 final,那麼任何嘗試覆蓋該函式的操作都將引發錯誤。

virtual void eat() final;

多型性

系統內部實際上是要查一個虛擬函式表,找到 eat() 的入口地址,從而呼叫父類或者子類的 eat() 函式,這就是執行時期的多型性

純虛擬函式【類似 Java 中的介面 interface】===> 函式原型後增加 = 0

純虛擬函式:沒有函式體,只有一個函式宣告

virtual void eat() = 0;

是在基類中宣告的虛擬函式,但是它在基類中沒有定義,但是要求任何派生類都要定義該虛擬函式自己的實現方法
注意:一旦一個類中有純虛擬函式了,那麼你就不能生成這個類的物件了【Java 中 interface 不能生成物件】
抽象類不能用來生成物件,主要目的用來統一管理子類物件

基類的解構函式一般寫成虛擬函式(虛解構函式)

// 1. 宣告一個 men 物件
Men men;
// 2. 寫法2:使用 new
Men *pmen = new Men();
delete pmen;  //  自己 new 的物件,必須使用 delete 呼叫解構函式


有一個問題

Human *phuman = new Men();  //  父類指標指向 子類物件
delete phuman;  //  沒有執行子類的解構函式

結論:用基類指標 new子類的物件,在 delete 的時候,系統不會呼叫派生類的解構函式,這肯定就有問題了

解決方式:

  1. 父類的解構函式寫成虛擬函式
  2. 繼承時候使用 public

相關文章