1. 虛函式的定義
在c++裡,虛函式的實現多型的一種方式或者說機制。對一般人來說,虛函式比較玄乎,很多人搞不清楚,今天就簡單來介紹下虛函式。虛函式是多型性的基礎,其呼叫方式是動態聯編(或者動態繫結),簡單來說,就是程式只有在執行時才決定呼叫的函式是基類的還是子類的。
2. 為何要使用虛函式
上面已經說到,虛函式是實現多型的一種機制。下面看乙個例子:
#include #include using namespace std;
class base
};class deriveda : public base
};class derivedb : public base
};int main()
程式執行結果是:
顯然,這不是我們想要的結果,程式的意圖是想通過基類base的指標指向子類,然後通過基本指標呼叫子類的方法,按照上面的實現方法,不能達到目的,呼叫的均是基本的print()方法。那麼應該如何實現呢?使用虛函式可以實現。看下面的**:
#include #include using namespace std;
class base
};class deriveda : public base
};class derivedb : public base
};int main()
程式輸出結果為
兩份**只有乙個地方有區別,就是在基類base的print函式前面新增了virtual關鍵字,這樣基類的print函式就是虛函式,子類繼承base的時候相應實現print函式(引數型別必須完全相同),這樣就能夠使用基類的指標來呼叫它指向的派生類的想對應的函式了
看到這裡,也許你會有疑問:第一種實現方法是符合多型性的啊,要呼叫driveda的print方法,只要建立乙個driveda的物件,然後呼叫print方法。如:
int main()
這也是多型。
不過,如果base類的子類有很多個,而且根據需求會不斷地增加子類,那麼在這種情況下,每次呼叫子類的print方法都通過建立子類物件來實現,建立物件過多,會導致效能下降,特別是呼叫該方法特別頻繁的時候。所以,使用虛函式,只需要宣告乙個基類指標,就能夠呼叫子類對應的方法,不但效能能夠提公升,**可讀性也提高了,降低了維護成本。
3. 析構函式與虛函式
在多型當中,一定要將基本的析構函式設定為虛函式並將其實現(可以為空),只有這樣,才能夠達到按物件構造的逆序來析構物件,否則,析構的時候,只會析構基類的那一部分,派生類的那一部分無法析構,看下面的**:
#include #include using namespace std;
class base
~base();
};class deriveda : public base
~deriveda()
};class derivedb : public base
~derivedb()
};int main()
剛接觸虛函式的同學可能看不出來這段**有什麼問題,如果派生類deriveda和derivedb如果動態申請記憶體了,並且在析構函式裡將其釋放了,可是還是會造成記憶體洩漏,因為派生類的析構函式沒有被呼叫,看輸出結果
派生類的析構函式沒有被呼叫,因為基類的析構函式沒有被宣告為虛函式,在釋放記憶體的時候,直接呼叫了基類的析構函式。
所以,需要將基類的析構函式宣告為虛函式,才能保證子類的析構函式被呼叫,輸出結果如下:
派生類物件正常析構,這就ok了
C 虛函式 純虛函式
1 基本概念 虛函式是在基類中使用關鍵字virtual宣告的函式。在派生類中重新定義基類中定義的虛函式時,會告訴編譯器不要靜態鏈結到該函式。我們想要的是在程式中任意點可以根據所呼叫的物件型別來選擇呼叫的函式,這種操作被稱為動態鏈結,或後期繫結。您可能想要在基類中定義虛函式,以便在派生類中重新定義該函...
C 虛函式 純虛函式
1.析構函式是否應為虛函式問題?2.成員函式的虛函式問題?3.析構函式是否可以為純虛函式問題?說明 僅在使用父類指標指向子類物件時有區別 當析構函式非虛函式時,使用父類指標指向子類物件,在析構時將不會呼叫子類析構函式 當析構函式是虛函式時,使用分類指標指向子類物件,在析構時會呼叫子類析構函式,且呼叫...
C 虛函式 純虛函式
include qdebug class animal void animal animal 即要實現基類animal的animal函式 假如在dog子類中沒有實現animal 函式,則會呼叫基類的animal 函式。即列印 what is the animal 假如在dog子類中實現了animal...