多型性是物件導向程式設計的三大特性之一。他使我們編寫的程式可以使用同一種函式方法處理同乙個基類下的同一層次的所有類的物件而產生不同的操作。多型性是利用基類的指標控制代碼和引用控制代碼,而不是利用名字控制代碼。
多型性就是不同的訊息傳送給各種不同的物件而產生不同的結果。
比如,乙個
animal
基類派生
bird
類,fish
類,people
類。而每個類中都含有
move
成員函式。對於每個派生類所例項化的物件,呼叫
move
函式產生的結果卻不相同。比如
bird
是飛,fish
是遊,people
是走。對於同樣的函式呼叫,以來每個物件自己做出恰當的想用,這就是多型性的關鍵思想。
普通繼承呼叫機制:
由於繼承的原理是「
si-a
」,也就是說,派生類就是基類。所以,基類的指標是可以指向派生類的。然而,當派生類重寫了基類的普通成員函式時,乙個基類指標指向派生類,此時,當此指標呼叫成員函式時,呼叫的是基類的成員函式。
如:class animal
};class people : public animal
};void main()
顯示如下:
i am animal;
i an people;
i am animal;//
基類指向派生類呼叫函式,呼叫的是基類的成員函式。
如果乙個基類指向乙個派生類,而希望呼叫乙個只有派生類才有的成員函式,會產生編譯錯誤。解決方法是強制性的顯式向下型別轉化。
virtual
函式(虛函式) 對於
virtual
函式,不再根據指標型別呼叫函式,而根據指標所指向的物件,呼叫函式。呼叫哪個類的成員函式不再是在編譯階段圈定(靜態聯編),而是動態的在執行階段懸在正確的成員函式(動態聯編)。
如乙個基類
shape
,派生類:
circle
,rectangle
,square
。他們都過載了基類
shape
中的虛函式
draw()
。當乙個基類指標指向它們,指標
->draw()
時,c++
根據指標指向的類呼叫此派生類中過載的
draw()
成員函式。
一旦乙個函式宣告為
virtual
,那它繼承層次中以下所有的派生類都預設為
virtual
函式(隱式預設)。但我們應該盡量顯式的宣告,其好處如下: 1.
清晰可見,使程式易懂,以維護。 2.
在乙個繼承層次中,如果我們要繼承乙個類,這個類中乙個
virtual
函式是隱式宣告的,如果我們以為他是乙個普通的成員函式而使用,那麼會出現一些邏輯錯誤。(而且特別不容易被發現!!!!)
對於乙個
virtual
函式,派生類中可以不過載,這樣編譯器會根據正常的繼承規則簡單的繼承基類的
virtual
函式。(下面說到的純虛函式必須顯式的進行過載。)
同樣是animal
基類的例子:
class animal
};class people : public animal
};class bird : public animal
};void main()
顯示:i am animal;
i am people;
i am bird;
同一基類指標指向不同的類,呼叫同樣的函式,產生不同的結果。這,就是多型的精髓!
抽象類和純虛函式
對於一些類,我們不打算去例項化,我們定義它僅僅是為了使用它去派生其他類,從而達到**重用的效果。這種類就是抽象類。我們通常使用抽象類作為基類(我實在想不到除了這個用處,抽象類還有什麼用),在抽象類中定義了它所要派生各種派生類的共有特性。通常我們定義的抽象類太過寬泛,無法在語義上例項化為乙個物件(當然,語法上也不能例項化)。比如,我們在上面定義的那乙個
animal
類,我們通常不把他例項化,因為「乙個動物」,確實太抽象了。所以,我們把它定義乙個抽象類,是乙個更好的選擇。
抽象類是不需要宣告的,只要類中含有乙個或多個純
virtual
函式,這個類就是抽象類。對於乙個抽象類,對它例項化會出現乙個編譯錯誤。
純虛函式:
virtual void fuction() = 0 ;
純虛函式沒有函式的具體實現。每個派生類都必須對它進行過載,提供這些函式的具體實現。它與虛函式的區別在於:虛函式提供的函式的具體實現,派生類具有是否過載虛函式的選擇權。而派生類必須對純虛函式進行過載。
語義上來說,當乙個基類無法對其派生類設定預設函式具體實現,即基類即使實現函式的具體實現,但對派生類來說沒有意義,即每個派生類都具有各自不同的函式具體實現時,這時候就要宣告為純虛函式。
如果乙個派生類沒有過載基類中的純虛函式,那麼這個派生類仍然是乙個抽象類。
多型性的重要應用舉例
多型性在軟體實現中具有非常重要的意義,它主要依靠虛函式和抽象類實現。
比如,再作業系統中,每個物理裝置會根據其特點執行迥然不同的操作。但對於作業系統來說,有些操作是沒有區別的。如,讀寫操作,對於具體的物理裝置來說,具體實現可能有所不同。但對於作業系統來說,是一樣的。而如果作業系統使用多型性的話,只要作業系統提供乙個裝置的抽象基類,然後再次抽象基類中定義共同的介面。這樣,對於不同的裝置,只要在裝置的驅動程式中繼承基類,並且在驅動程式中實現物理裝置的具體實現就可以了,而不需要更改作業系統的任何檔案。
再比如,定義乙個指向基類的指標陣列,他同樣可以指向任何由基類派生出來的派生類。這樣,就可以對這個陣列的所有元素呼叫基類的虛函式,而對於每個元素,他會更具指標所指向的物件而呼叫函式。
C 的多型性 筆記
第一節課 分類 靜態多型 函式的過載和運算子過載屬於靜態多型,復用函式名 動態多型 派生類和虛函式實現執行時多型。靜態多型和動態多型區別 include using namespace std 多型 動物類 class animal 派生類貓類 class cat public animal 執行說...
C 的多型性
c 的多型性 1.多型性的概念 多型性是指用乙個名字定義不同的函式,這函式執行不同但又類似的操作,從而實現 乙個介面,多種方法 多型性的實現與靜態聯編 動態聯編有關。靜態聯編支援的多型性稱為編譯時的多型性,也稱靜態多型性,它是通過函式過載和運算子過載實現的。動態聯編支援的多型性稱為執行時的多型性,也...
有關C 多型性
c 多型性是通過虛函式來實現的,虛函式允許子類重新定義成員函式,而子類重新定義父類的做法稱為覆蓋 override 或者稱為重寫。這裡我覺得要補充,重寫的話可以有兩種,直接重寫成員函式和重寫虛函式,只有重寫了虛函式的才能算作是體現了c 多型性 而過載則是允許有多個同名的函式,而這些函式的引數列表不同...