多型是面向物件的程式設計的關鍵技術。多型:呼叫同一個函式名,可以根據需要但實現不同的功能。多型體現在兩個方面,我們以前學過的編譯時的多型性(函式過載)和現在我們這一章將要學習的執行時的多型性(虛擬函式)。
執行時多型:執行時的多型性是指在程式執行之前,根據函式名和引數無法確定應該呼叫哪一個函式,必須在程式的執行過程中,根據具體的執行情況來動態地確定。
前面我們在介紹繼承的時候,通過基類的指標或引用指向派生類物件後,呼叫派生類和基類中同名的方法的時候,呼叫的均是基類的成員,不能訪問派生類的成員。這是在執行之前就可以確定的,而要實現執行時的多型,我們要通過虛擬函式來實現。
多型使用
1.若要訪問派生類中相同名字的函式,必須將基類中的同名函式定義為虛擬函式,基類的指標指向派生類物件後, 就可以呼叫派生類的同名的成員函式。
CCurrentTime currentTime;
CTime *p = ¤tTime;
CTime& time = currentTime;
time.getHour();
在前面我們沒有將基類的getHour函式設定為虛擬函式,所以雖然這是一個包含派生類的物件的基類的引用,它也不能根據我們剛才所說的執行時多型來判斷所包含的物件來呼叫該類的getHour函式,只會根據基類的這是一個基類的引用來呼叫基類的getHour函式,指標也是一樣。
1)將基類同名的函式定義為虛擬函式可以使用C++關鍵字virtual來實現。在基類成員函式宣告前加virtual關鍵字。
2)在派生類中重新定義基類中的虛擬函式時,可以不用關鍵字virtual來修飾這個成員函式 。
在程式的執行過程中,依據指標具體指向哪個類物件,或依據引用哪個類物件,才能確定繫結哪個成員函式,實現動態繫結。
注意:
1)當在基類中把成員函式定義為虛擬函式後,在其派生類中定義的虛擬函式必須與基類中的虛擬函式同名,引數的型別、順序、引數的個數必須一一對應,若函式名相同,但引數的個數不同或者引數的型別不同時,則屬於函式的過載,而不是虛擬函式。若函式名不同,顯然這是不同的成員函式。
2)實現這種動態的多型性時,必須使用基類型別的指標變數,並使該指標指向不同的派生類物件,並通過呼叫指標所指向的虛擬函式才能實現動態的多型性。通過物件名訪問虛擬函式則不會實現動態多型性。
3)在派生類中沒有重新定義虛擬函式時,與一般的成員函式一樣,當呼叫這種派生類物件的虛擬函式時,則呼叫其基類中的虛擬函式。
4)可把解構函式定義為虛擬函式,但是,不能將建構函式定義為虛擬函式。建構函式不能被繼承,每一個類都需要自己的建構函式來初始化物件。當派生類的物件銷燬的時候,先呼叫派生類的解構函式,再呼叫基類的解構函式,如果基類的解構函式不是虛擬函式,在對基類的指標或者引用進行銷燬的時候,呼叫的就是基類的解構函式,沒有呼叫派生類的解構函式,一般的情況下這是沒有問題的。但是我們如果需要在派生類的內部執行一些必要的清理工作,比如釋放一些佔用的記憶體,或者釋放佔用執行緒的鎖,這個時候不呼叫派生類的解構函式就會導致記憶體洩漏。我們一般講基類的解構函式設定為虛擬函式。
5)多型時通過虛擬函式動態繫結實現。內部則是通過虛擬函式表實現。呼叫時的執行速度要慢。虛擬函式表是一張表,其內部儲存很多虛擬函式的地址。基類物件有一張,子類也有一張,初始時子類繼承基類的表,若子類覆蓋(重寫)了基類的虛擬函式,則將子類的虛擬函式表對應專案替換為子類虛擬函式指標。
這個大家先大概瞭解,隨著理解的加深,可以深入學習一下。
原文連結:http://www.maiziedu.com/wiki/cplus/forms/