關於建構函式和析構函式
在整理排序演算法的時候想到可以藉此熟悉一下類的構造以及繼承等知識點,就寫了乙個排序基類宣告乙個排序函式,然後寫多個排序演算法的子類重寫這個排序函式,過程中順便研究了一下virtual和多型的概念。
首先回顧一下虛函式和純虛函式的八股文,虛函式是多型的實現機制,宣告乙個虛函式就是在乙個函式的宣告(不需要定義)前加上virtual
,而純虛函式則還要函式宣告後加上=0
來表明純虛函式身份,如果想要定義純虛函式的實現,則必須在類外部進行定義,例子:
// 純虛函式
virtual
voida(
)=0;
// 虛函式
virtual
voidb(
)
先看虛函式,虛函式使得乙個指向子類物件的基類型別的指標可以重寫基類函式,當然各自型別的物件都是能實現本類的函式的,看一下例子:
class
foo// 非虛函式
voidc(
)};class
bar:
public foo
// 重寫非虛函式
voidc()};
如果通過建立兩個類的物件呼叫函式:
int
main()
但如果利用指標來呼叫函式:
int
main()
也就是說如果是通過指向子類物件的基類型別指標來呼叫函式,可以呼叫子類重寫的虛函式,但非虛函式還是會呼叫基類本身的。然後這裡注意一下,指標用->
呼叫函式。
在我的理解中,多型分為編譯時多型和執行時多型,編譯時多型的話主要就是指方法的過載,即多個同名不同參的函式,而執行時多型基本上就是指父類指標指向子類物件的情況。
多型的實現依賴於動態繫結技術,而動態繫結技術的核心是虛函式表。乙個類如果包含虛函式,就會同時有一張對應的虛函式表,虛函式表裡儲存了指向各個虛函式的指標,但非虛函式不會被包含在虛函式表裡。如果乙個類的子類也包含虛函式表,那麼子類中的虛函式表會指向子類的虛函式,也就是說如果子類重寫了基類的虛函式,那麼子類的虛函式表內指向該函式的指標就會指向子類所寫的虛函式,若沒有重寫,那麼就指向基類的虛函式。
如圖:
**上圖中b是a的子類,c是b的子類,b重寫了vfunc1(),c改寫了vfunc2()。
包含純虛函式的類叫做純虛類,純虛類是不能建立物件的,必須要建立子類通過子類建立物件:
class
foo~
foo(
)// 純虛函式
virtual
voida(
)=0;
// 虛函式
virtual
voidb(
)voidc(
)};class
bar:
public foo
~bar()
// 重寫純虛函式
voida(
)// 重寫虛函式bar
voidb(
)// 重寫非虛函式
voidc()};
假如有以上兩個類,當我們為兩個類建立物件時,要注意:
不可以直接為foo類建立物件,比如foo a;
就會報錯,因為foo是乙個純虛類不能直接建立物件,但是我們可以建立乙個foo類的指標,因為指標有可能指向foo的子類bar物件,比如foo *a = new bar;
這是被允許的。
在bar子類裡,必須重寫純虛函式a,但b可以不重寫,因為基類已經提供了b函式的實現。
這裡是如何體現多型的呢,包括以下兩個方面:
建構函式不能是虛函式,析構函式可以是虛函式且最好為虛函式。
C 多型, 虛函式, 純虛函式
多型 不同物件接收相同的訊息產生不同的動作。多型包括 編譯時多型和 執行時多型 執行時多型是 通過繼承和虛函式來體現的。編譯時多型 運算子過載上。封裝可以隱藏實現細節,使得 模組化 繼承可以擴充套件已存在的 模組 類 它們的目的都是為了 重用。多型也有 重用的功能,還有解決專案中緊耦合的問題,提高程...
C 多型 虛函式 虛析構函式以及虛函式表
什麼是多型 指不同物件收到相同訊息時或相同物件收到不同訊息時產生不同的動作。這裡先說下為什麼會用到虛函式 以下面的程式為例 這個程式中,carp是fish的繼承類,而carp中覆蓋了swim這個方法,在makefishswim這個函式中,要使用fish類的形參,而你將yourfish這個carp類的...
多型,虛函式,純虛函式
多型 借助虛函式,基類指標既可以使用基類 父類 的成員函式,也可以使用派生類 子類 的成員函式,它有多種形態,或多種表現方式,這就是多型 簡單說就是同一條語句可以執行不同的操作,看起來有不同表現方式,這就是多型。多型存在的三個條件 注意 派生類 子類 中的虛函式必須覆蓋 不是過載 基類 父類 中的虛...