解構函式前加virtual關鍵字的作用?
阿新 • • 發佈:2019-01-30
大家知道,解構函式是為了在物件不被使用之後釋放它的資源,虛擬函式是為了實現多型。那麼把解構函式宣告為vitual有什麼作用呢?請看下面的程式碼:
先看程式輸出結果:
程式碼第36行可以正常釋放pTest1的資源,而程式碼第42行沒有正常釋放pTest2的資源,因為從結果看Derived類的解構函式並沒有被呼叫。通常情況下類的解構函式裡面都是釋放記憶體資源,而解構函式不被呼叫的話就會造成記憶體洩漏。原因是指標pTest2是Base型別的指標,釋放pTest2時只進行Base類的解構函式。在程式碼第8行前面加上virtual關鍵字後的執行結果如下:
此時釋放指標pTest2時,由於Base的解構函式是virtual的,就會先找到並執行Derived類的解構函式,然後再執行Base類的解構函式,資源正常釋放,避免了記憶體洩漏。
因此,只有當一個類被用來作為基類的時候,才會把解構函式寫成虛擬函式。
#include<iostream> using namespace std; class Base { public: Base() {}; //Base的建構函式 ~Base() //Base的解構函式 { cout << "Output from the destructor of class Base!" << endl; }; virtual void DoSomething() { cout << "Do something in class Base!" << endl; }; }; class Derived : public Base { public: Derived() {}; //Derived的建構函式 ~Derived() //Derived的解構函式 { cout << "Output from the destructor of class Derived!" << endl; }; void DoSomething() { cout << "Do something in class Derived!" << endl; }; }; int main() { Derived *pTest1 = new Derived(); //Derived類的指標 pTest1->DoSomething(); delete pTest1; cout << endl; Base *pTest2 = new Derived(); //Base類的指標 pTest2->DoSomething(); delete pTest2; return 0; }
先看程式輸出結果:
1 Do something in class Derived!
2 Output from the destructor of class Derived!
3 Output from the destructor of class Base!
4
5 Do something in class Derived!
6 Output from the destructor of class Base!
程式碼第36行可以正常釋放pTest1的資源,而程式碼第42行沒有正常釋放pTest2的資源,因為從結果看Derived類的解構函式並沒有被呼叫。通常情況下類的解構函式裡面都是釋放記憶體資源,而解構函式不被呼叫的話就會造成記憶體洩漏。原因是指標pTest2是Base型別的指標,釋放pTest2時只進行Base類的解構函式。在程式碼第8行前面加上virtual關鍵字後的執行結果如下:
1 Do something in class Derived! 2 Output from the destructor of class Derived! 3 Output from the destructor of class Base! 4 5 Do something in class Derived! 6 Output from the destructor of class Derived! 7 Output from the destructor of class Base!
此時釋放指標pTest2時,由於Base的解構函式是virtual的,就會先找到並執行Derived類的解構函式,然後再執行Base類的解構函式,資源正常釋放,避免了記憶體洩漏。
因此,只有當一個類被用來作為基類的時候,才會把解構函式寫成虛擬函式。