【c++】28.虚析构函数、纯虚函数
1.虛函數:在類的成員函數前面加virtual關鍵字的函數;
一般把虛函數定義在public區,方便在主函數中調用
如果一個類有一個虛函數,則該類就有一個虛函數列表,所有該類的對象都共享這個虛函數表;(QT調試過程中顯示的是vptr)
如果一個類有一個或者一個以上的虛函數,則該類有且只有一張虛函數表,每個類都只有一個虛函數表,該類的所有對象都共享這張虛函數表。
子類的虛函數表中子類的虛函數覆蓋父類的虛函數的情況,當子類將父類的虛函數override時,就覆蓋了父類的虛函數;
滿足override的條件:函數名相同,函數的返回值相同,形參列表相同;
純虛函數:形式為virtual void fun1() = 0;
純虛函數不需要實現,原因是不會被調用到;
抽象基類:至少有一個純虛函數的類;
- 抽象基類不能產生該類的對象,但可以有該類的指針或引用;
- 在子類中必須將父類的純虛函數實現,不然該子類也是抽象基類;
2.當一個類有子類時,該類的析構函數必須是虛函數,原因:會有資源釋放不完全的情況;
下面內容來自另一博客: http://c.biancheng.net/view/269.html
我們知道,有時會讓一個基類指針指向用 new運算符動態生成的派生類對象;同時,用new運算符動態生成的對象都是通過delete指向它的指針來釋放的。如果一個基類指針指向用 new運算符動態生成的派生類對象,而釋放該對象時是通過釋放該基類指針來完成的,就可能導致程序不正確。
例如下面的程序:
#include <iostream> using namespace std; class CShape //基類 { public:~CShape() { cout << "CShape::destrutor" << endl; } }; class CRectangle : public CShape //派生類 { public:int w, h; //寬度和高度~CRectangle() { cout << "CRectangle::destrutor" << endl; } }; int main() {CShape* p = new CRectangle;delete p;return 0; }程序的輸出結果如下:
CShape::destrutor
輸出結果說明,delete p;只引發了 CShape 類的析構函數被調用,沒有引發 CRectangle 類的析構函數被調用。這是因為該語句是靜態聯編的,編譯器編譯到此時,不可能知道此時 p 到底指向哪個類型的對象,它只根據p的類型是 CShape * 來決定應該調用CShape類的析構函數。
按理說,delete p;會導致一個CRectangle類的對象消亡,應該調用 CRectangle 類的析構函數才符合邏輯,否則有可能引發程序的問題。
例如,假設程序需要對 CRetangle類的對象進行計數(即統計 CRetangle類有多少個存活的實例化對象),如果此處不調用 CRetangle 類的析構函數,就會導致計數不正確。
再如,假設CRectangle 類的對象在存續期間進行了動態內存分配,而釋放內存的操作都是在析構函數中進行的,如果此處不調用 CRetangle 類的析構函數,就會導致被釋放的對象中動態分配的內存以后再也沒有機會回收。
綜上所述,人們希望delete p;這樣的語句能夠聰明地根據p 所指向的對象執行相應的析構函數。實際上,這也是多態。為了在這種情況下實現多態,C++規定,需要將基類的析構函數聲明為虛函數,即虛析構函數。
改寫上面程序中的CShape類,在析構函數前加 virtual關鍵字,將其聲明為虛函數:
class CShape{ public:virtual ~CShape() { cout << "CShape::destrutor" << endl; } };則程序的輸出變為:
CRectangle::destrutor CShape::destrutor說明 CRetangle類的析構函數被調用了。實際上,派生類的析構函數會自動調用基類的析構函數。
只要基類的析構函數是虛函數,那么派生類的析構函數不論是否用virtual關鍵字聲明,都自動成為虛析構函數。
一般來說,一個類如果定義了虛函數,則最好將析構函數也定義成虛函數。
析構函數可以是虛函數,但是構造函數不能是虛函數。
總結
以上是生活随笔為你收集整理的【c++】28.虚析构函数、纯虚函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【c++】27.事件驱动、IO复用、se
- 下一篇: 【c++】29.设计模式总结