虛析構函數
在C++中,不能把建構函數定義為虛構造函數,因為在實例化一個物件時才會呼叫建構函數,且虛函數的實現,其實本質是透過一個虛函數表指標來呼叫的,還沒有物件更沒有記憶體空間當然無法呼叫了,故沒有實例化一個物件之前的虛構造函數沒有意義也不能實現。
但析構函數卻是可以為虛函數的,且大多時候都宣告為虛析構函數。這樣就可以在用基底類別的指標指向衍生類別的物件在釋放時,可以根據實際所指向的物件類型動態聯編呼叫子類別的析構函數,實現正確的物件記憶體釋放。
下面我們來做個實驗,請看程式碼:
/**************************************//Des:C++教學demo//Author: Huang//Copyright:www.dotcpp.com//Date:2017/12/27******************************* *******/#include<iostream>usingnamespacestd;classPoint{private:intx,y;int*str;public:Point(intx=0,inty=0){this->x=x;this-> y=y;str=newint[100];}~Point(){delete[]str;cout<<CalledPoint'sDestructorandDeletedstr!<<endl;}};classCircle:publicPoint{private:intr;int*str;public: Circle(intx,inty,intR):Point(x,y){r=R;str=newint[100];}~Circle(){delete[]str;cout<<CalledCircle'sDestructorandDeletedstr!<<endl;} };intmain(){Point*p;p=newCircle(10,10,20);deletep;return0;}
可以看到程式碼,基底類別中沒有用virtual聲明的析構函數,且基底類別和衍生類別當中都有動態記憶體開闢,那麼我們在主函數中也動態開闢記憶體的方式建立一個Circle類,然後刪除,之後運行後截圖如下:
可以清楚的看到,僅僅呼叫了基底類別的析構函數,這樣一來衍生類別中new出來的4*100位元組的記憶體就會殘留,造成記憶體洩漏!
而如果把基底類別中析構函數宣告為virtual,則結果大有不同!這時候多型效應出現,會先呼叫釋放衍生類別的空間,然後再釋放基底類別的記憶體空間,完美結束,如下圖:
以上,這就是虛析構函數帶來的好處,大家自行體會。