標籤:
在類中,有兩個與眾不同的成員函數,那就是建構函式和解構函式。當建構函式與解構函式遭遇繼承和多態,它們的健全狀態又會出現什麼變化呢?
多態性是在父類或各子類中執行最合適成員函數。一般來說,只會選擇父類或子類中的某一個成員函數來執行。這可給解構函式帶來了麻煩!如果有的資源是父類的建構函式申請的,有的資源是子類的建構函式申請的,而虛函數只允許程式執行父類或子類中的某一個解構函式,豈不是註定有一部分資源將無法被釋放?為瞭解決這個問題,虛解構函式變得與眾不同。
下面我們就來給解構函式的前面加上保留字virtual,看看啟動並執行結果會怎麼樣:(程式17.8)
//animal.h#include <iostream>using namespace std;class Animal{ public: Animal(int w=0,int a=0); virtual ~Animal();//虛解構函式 protected: int weight,age;};Animal::Animal(int w,int a){ cout <<"Animal consturctor is running..." <<endl; weight=w; age=a;}Animal::~Animal(){ cout <<"Animal destructor is running..." <<endl;}//cat.h#include "animal.h"class Cat:public Animal{ public: Cat(int w=0,int a=0); ~Cat();};Cat::Cat(int w,int a):Animal(w,a){ cout <<"Cat constructor is running..." <<endl;}Cat::~Cat(){ cout <<"Cat destructor is running..." <<endl;}//main.cpp#include "cat.h"int main(){ Animal *pa=new Cat(2,1); Cat *pc=new Cat(2,4); cout <<"Delete pa:" <<endl; delete pa; cout <<"Delete pc:" <<endl; delete pc; return 0;}
運行結果:
Animal consturctor is running...Cat constructor is running...Animal consturctor is running...Cat constructor is running...Delete pa:Cat destructor is running...Animal destructor is running...Delete pc:Cat destructor is running...Animal destructor is running...
我們驚訝地發現,虛解構函式不再是運行父類或子類的某一個解構函式,而是先運行合適的子類解構函式,再運行父類解構函式。即兩個類的解構函式都被執行了,如果兩塊資源分別是由父類建構函式和子類建構函式申請的,那麼使用了虛解構函式之後,兩塊資源都能被及時釋放。
我們修改程式17.8,將Animal類解構函式前的virtual去掉,會發現運行結果中刪除pa指向的Cat對象時,不執行Animal類的解構函式。如果這時Cat類的建構函式裡申請了記憶體資源,就會造成記憶體流失了。
所以說,虛函數與虛解構函式的作用是不同的。虛函數是為了實現多態,而虛解構函式是為了同時運行父類和子類的解構函式,使資源得以釋放。
C++虛函數與虛解構函式