一、多型的概念
多型通俗來說,就是多種形態,完成某個行為,當不同的物件去完成某個行為時會產生不同的狀態。
二、多型的定義及實現
1、多型定義的構成條件
多型是在不同繼承關係的類物件,去呼叫同一函式,產生了不同行為。
例如在火車站買票時,學生和**分別去買票,學生買的是半價票,**買的是全價票。同樣是買票,但是不同的物件去買票時產生了不同的行為。
在繼承時要構成多型還有兩個重要的條件:
(1)呼叫函式的物件必須是指標或者引用;
(2)被呼叫的函式必須是虛函式,且完成了虛函式的重寫。
首先解釋一下第乙個條件:
class person
};class student :public person
};void func(person p)
int main()
觀察上面這段**,發現呼叫函式的物件不是指標或者引用,當把ps物件傳過去時,p是對ps的乙份拷貝;當把st物件傳過去時,p是對st的切片,也就是只把父類的那一部分切了過去,根本上還是父類物件在呼叫。並不是不同繼承關係的類物件,呼叫同一函式。可以看下面輸出**,發現買的都是全價票。
對於為什麼必須要傳指標或者引用,我簡單說一下,傳指標是因為,傳參的時候若傳的是父類物件,指標則指向父類物件,若是子類,就指向子類物件;而引用是物件的別名,傳哪個物件就是哪個物件的別名。
總結一下:構成多型----->和物件有關;不構成多型----->跟型別有關。
其次關於虛函式我做以下介紹:
(1)虛函式的概念
虛函式就是在成員函式前面加上virtual關鍵字。
(2)虛函式的重寫
在派生類中有乙個跟基類完全相同的虛函式,我們就稱子類的虛函式重寫了基類的虛函式,完全相同是指:函式名、引數、返回值都相同。另外虛函式的重寫也叫虛函式的覆蓋。
(3)虛函式重寫的例外
重寫虛函式的返回值可以不同,但是分別必須是基類指標和派生類指標或者基類引用和派生類引用。
(4)不規範的函式重寫行為
在派生類中重寫的成員函式可以不加virtual關鍵字,也是構成重寫的,因為繼承後基類的虛函式被繼承下來在派生類中依舊保持虛函式屬性,我們只是重寫了它。
(5)析構函式的重寫行為
基類中的析構函式如果是虛函式,那麼派生類中的析構函式就重寫了基類的析構函式。雖然基類和父類的析構函式名稱不同,看起來不符合重寫的規則,事實卻並非如此,這裡可以理解為編譯器對析構函式的名稱做了特殊處理,編譯之後,析構函式的名稱統一處理成了destructor,由此也說明基類的析構函式最好也寫成虛函式。
若不寫成虛函式,未構成多型,則是普通函式的呼叫,只與型別有關:
class person
};class student :public person
};int main()
輸出結果:
可以看出,st是person型別的指標,雖然指向了子類的建構函式,但是只完成了切片,只拿到了子類中父類的那部分,調了父類的析構函式。此時子類並沒有被析構,造成了記憶體洩露。需要注意的是析構時,底層是這樣實現的,先過載了ps->distructor(),然後再free(ps)。
寫成了虛函式,則構成了多型:
三、介面繼承和實現繼承
普通函式的繼承是一種實現繼承,派生類繼承了基類函式,可以使用函式,繼承的是函式的實現。虛函式的繼承是一種介面繼承,派生類繼承的是基類虛函式的介面,目的是為了重寫,達成多型,繼承的是介面。所以如果不實現多型,就不要把函式定義成虛函式。
四、抽象類
抽象類從字面上可以理解為現實世界沒有的,用來描述一些比較泛化的不具體的類別。
在虛函式的後面寫上=0,則這個函式為純虛函式。包含純虛函式的類叫做抽象類(也叫介面類),抽象類不能例項化出物件。派生類繼承後也不能例項化出物件(也就是派生類繼承了基類的純虛函式),只有重寫虛函式,派生類才能例項化出物件。純虛函式規範了派生類必須重寫,另外純虛函式更體現了介面繼承。
下面 一段**來演示一下抽象類:
class car
;class person :public car
;int main()
輸出結果:
可以看出上述**執行出錯,子類person繼承了父類的純虛函式,是抽象類,不能例項化出物件,所以子類必須完成虛函式的重寫,不然就沒有意義。
因此得出乙個結論,純虛函式是一種強制派生類重寫虛函式的一種機制。
在實際中,c++11提供override和final來修飾虛函式
首先看一段**:
class car
;class person :public car
};int main()
輸出結果:
可以看出override修飾派生類虛函式強制完成重寫。
下面再介紹一下final關鍵字,它修飾基類的虛函式不能被派生類重寫
class car
};class person :public car
};int main()
輸出結果:
以上是關於多型的基礎知識點,下篇部落格將介紹多型的原理。
關於物件導向多型的理解
子類物件位址可以賦值給父類指標,可以通過父類指標呼叫與子類函式名和參數列相同的虛函式,在程式執行時,當父類指標指向父類物件的位址時則呼叫父類的虛函式,當父類的指標指向子類物件的位址時呼叫子類的虛函式,讓同一條函式語句呼叫達成不同的結果。比如學校發通知元旦班級要有人去表演,同學a可以代表我們班去表演,...
物件導向 多型
繼承是多型的基礎,是指物件的多種形態 1.引用的多型 1 父類的引用可以指向本類的物件 2 父類的引用可以指向子類的物件 注意 子類的引用不能指向父類的物件 2.方法的多型 1 建立本類物件時,呼叫的方法是本類的方法 2 建立子類物件時,呼叫的方法是子類重寫的方法或是繼承的方法 注意 如果是子類獨有...
物件導向 多型
多型可以簡單的概括為 乙個介面,多種方法 在程式執行過程中才決定呼叫的函式,簡單的說就是,允許將子類型別的指標賦值給父類型別的指標,賦值後,父類物件就可以根據當前賦給它的子類物件的特徵以不同的方式執行。容易混淆的兩個概念 是指允許存在多個同名的函式,而這些函式的參數列不同 或許引數個數不同,或許引數...