(2)多型是物件導向的重要技術之一,它是一種行為的封裝,是同乙個事物所表現出來的多種形態,簡單地說就是:乙個介面、多種形態。
(3)在執行時使用同乙個成員名來呼叫類物件的成員函式,會呼叫哪個物件的成員函式呢?這就是多型要解決的問題!
(1)多型技術允許將基類指標或基類引用指向派生類物件。
(2)把不同派生類的物件都當作基類物件來看待,可以遮蔽不同派生類之間的差異,從而寫出通用的**以適應需求的不斷變化。
(1)多型分為兩種:
(1)在c++中,基類指標是用來指向基類物件的,如果用它來指向派生類物件,則進行指標型別轉換(上行轉換),將派生類指標轉換為基類指標,所以該指標將會指向派生類物件中的基類部分,通過該指標是無法呼叫派生類物件中的成員函式的。
但是,虛函式突破了這一限制。在派生類的基類部分中,派生類的虛函式取代了基類原來的同名虛函式,因此在使基類指標指向派生類物件後,使用該基類指標呼叫這個同名虛函式成員時就呼叫了派生類的虛函式。
(2)當把基類的某個成員函式宣告為虛函式時,c++允許在其派生類中對該虛函式進行重新定義,賦予它新的功能,並且可以通過基類指標指向同一類族的不同派生類的物件,來呼叫相應派生類中的該同名虛函式。
由虛函式實現的動態多型性就是:同一族類中不同的派生類物件,對用一函式呼叫作出不同的響應.
(3)虛函式的使用方法如下:
(4)c++規定,當乙個成員函式被定義為虛函式後,其派生類中的同名函式都自動成為虛函式(而不一定要有關鍵字virtual顯示宣告了),但是為了清晰,習慣上每一層都加上virtual關鍵字。
舉例:
#includeusing namespace std;
class base
virtual void g()
void my()
};class derive: public base
void g()
void my()
};int main()
(1)應該考慮:對成員函式的呼叫是通過物件名還是通過基類指標或是基類引用去訪問。如果是後兩者,則應當宣告為虛函式。
(2)虛函式:如果乙個類中定義了虛函式virtual,那麼這個虛函式是被實現的,其作用就是為了讓該虛函式在這個類的的派生類中被覆蓋,被實現為不同的功能,從而結合基類指標以實現動態多型性。
(3)純虛函式:有時,在定義乙個虛函式時,並不定義其函式體,即它的函式體是空的,它的作用只是保留乙個虛函式名,它關注的是介面的統一性,其具體的功能實現由它的派生類完成。比如:virtual float area(float a,float b ) = 0;
最後面的「=0」的作用僅僅只是告訴編譯器這是乙個純虛函式。
純虛函式只具有函式的名稱,沒有函式體,不具備函式的功能,因此不能被呼叫。只有在其派生類中被重新定義過之後才具備函式的功能,才能被呼叫。
如果在乙個類中宣告了純虛函式,但是在其派生類中該純虛函式並沒有被定義,那麼該虛函式在這個派生類中仍然為純虛函式,仍然不具備函式的功能。
(4)抽象類與抽象基類:不用來定義物件而只作為一種基本型別用作被繼承的類,稱為抽象類;由於它經常用來作基類,故又被稱之為抽象基類。凡是包含純虛函式的類,都是抽象類,這種類不能直接生成物件(例項),它的作用就是作為乙個類族的共同基類,或者說是為乙個類族提供乙個公共介面。
(5)需要說明的是,使用虛函式,系統要有一定的空間開銷。當乙個類中含有虛函式時,編譯系統會為它構造乙個虛函式指標vptr(4位元組),同時這個虛函式指標指向乙個虛函式表vtable,虛函式表是乙個指標陣列,存放的是該類中的每個虛函式的入口位址。(查表是高效的,因此多型性是高效的。)
(1)當派生類的物件從記憶體中撤銷時,一般先呼叫派生類的析構函式釋放該物件中的派生類部分,再呼叫基類的析構函式釋放該物件中的基類部分,從而能夠完整的釋放該物件記憶體。
(2)但是,當用基類指標指向了乙個派生類物件,即 base *bptr = new child;此時用delete bptr;來撤銷bptr 指向的動態儲存空間時,只會執行基類的析構函式來釋放該堆記憶體中的基類部分,但是並不會執行派生類的析構函式來釋放該堆記憶體中的派生類部分。此時,就會造成記憶體洩漏現象。
(3)為了避免此類現象發生,我們將基類的析構函式宣告為虛析構函式,這樣就解決了上述問題(即先呼叫派生類的析構函式釋放該動態空間中的派生類部分,再呼叫基類的析構函式釋放該動態空間中的基類部分,從而能夠完整的釋放該堆記憶體)。
(4)如果將基類的析構函式宣告為虛析構函式,那麼該基類的所有派生類的析構函式都自動成為虛析構函式。
答:分別簡單講述一下函式過載、函式覆蓋、函式隱藏的概念與特徵:
函式過載:過載函式通常用來命名一組功能相似的函式。
(1)兩個函式要在相同的類域
(2)兩個函式的名稱相同
(3)兩個函式的的形參列表必須不同
函式覆蓋:覆蓋是指派生類函式覆蓋基類函式。
(1)兩個函式要在不同的類域
(2)兩個函式的名稱相同
(3)基類函式必須是虛函式
(4)兩個函式的形參列表和返回值型別要相同
函式隱藏:指派生類的函式遮蔽了與其同名的基類函式。
(1)兩個函式在不同的類域
(2)兩個函式的名稱相同
(3)兩個函式的形參列表不同
(4)如果派生類函式與基類函式形參列表相同,但是在基類函式中沒有virtual關鍵字,也會發生函式隱藏
C 多型性與虛函式
物件導向程式設計中的多型性是指向不同的物件傳送同乙個訊息,不同物件對應同一訊息產生不同行為。在程式中訊息就是呼叫函式,不同的行為就是指不同的實現方法,即執行不同的函式體。也可以這樣說就是實現了 乙個介面,多種方法 從實現的角度來講,多型可以分為兩類 編譯時的多型性和執行時的多型性。前者是通過靜態聯編...
C 多型性 與 虛函式
1.運算子過載 運算子過載形式 1 過載為類的成員函式 運算子過載函式說明為類的成員函式的格式為 類名 operator 運算子 參數列 如 c1 c2 編譯器將給出的解釋為 c1.operator c2 該運算子過載函式僅僅有乙個引數,所以過載為成員函式時,雙目運算子僅有乙個引數。對於單目運算子,...
C 多型性與虛函式
多型性是物件導向程式設計的關鍵技術之一。利用多型性技術,可以呼叫同乙個函式名的函式,實現完全不同的功能。若程式語言不支援多型性,不能稱為物件導向的語言。在c 中有兩種多型性 1 定義格式 虛函式是乙個類的成員函式,定義格式如下 virtual 返回型別 函式名 參數列 說明 2 通過虛函式實現多型性...