析構函數爲什麼要寫成虛函數,什麼情況下寫成虛函數,寫成虛函數解決了什麼問題, 解決問題的深層原理是什麼?
前邊都是表層,最後一個問題也困擾我了好一陣..
// Created by yanpan on 2019/5/10.
#include <iostream>
using namespace std;
class Base
{
public:
Base(){cout << "Base()" << endl;}
Base(int num): _bnum(num){cout << "Base(int)" << endl;}
void show()
{
cout << "_bnum: " << _bnum << endl;
}
~Base(){cout << "~Base()" << endl;} //none virtual destructor函數
private:
int _bnum;
};
class Derive: public Base
{
public:
Derive(){cout << "Derive()" << endl;}
Derive(int num): _dnum(num){cout << "Derive(int)" << endl;}
virtual ~Derive(){cout << "~Derive()" << endl;}
private:
int _dnum;
};
int main()
{
Base* base = new Derive();
delete base;
return 0;
}
運行結果:程序運行崩潰
崩潰的原因:調用了基類的析構函數,沒有調用派生的析構函數,導致資源沒有得到正確的釋放。
解決的辦法:實現動多態,把基類的析構函數寫成虛函數 運行正確
class Base
{
public:
Base(){cout << "Base()" << endl;}
Base(int num): _bnum(num){cout << "Base(int)" << endl;}
void show()
{
cout << "_bnum: " << _bnum << endl;
}
virtual ~Base(){cout << "~Base()" << endl;}
private:
int _bnum;
};
爲什麼虛析構函數可以解決這個問題,寫成虛函數會發生多態,多態在運行的時候才知道調用哪個函數,在運行的時候找到虛函數指針,該指針是指向派生類虛函數表,調用派生類的析構函數。派生類的析構函數調用後自動調用基類的析構函數。所以,派生類對象調用了析構後 基類隨後就調用了析構函數.
問題一: 繼承的時候不會繼承基類的構造函數和析構函數
問題二:基類的析構函數和派生類的析構函數不是同名的函數
解答:編譯器對析構函數有一個統一的命名,destructor,這樣就解決了派生類虛函數表裏邊派生類析構函數覆蓋基類的析構函數