多態使用時,如果子類有對象開辟到堆區,那么父類指針在釋放時無法調用到子類的析構代碼
解決方式:將父類中的析構函數改為虛析構或者春虛析構
虛析構和純虛析構的共性:
- 可以解決父類指針釋放子類對象
- 都需要有具體的函數實現
虛析構和純虛析構的區別:
- 如果是純虛析構,該類屬於抽象類,無法實例化對象
虛析構語法:
virtual ~類名(){}
純虛析構語法:
virtual ~類名()=0; 類名::類名(){};
常規操作:
#include<iostream> using namespace std; class animal { public: virtual void speak() = 0; }; class dog : public animal { public: void speak() { cout << "小狗在說話" << endl; } }; class cat : public animal { public: void speak() { cout << "小貓在說話" << endl; } }; void test01() { animal* it = new cat; it->speak(); delete it; } int main() { test01(); system("pause"); }
但是如果子類對象有開辟空間到堆區時,在子類中創建指針:
class cat : public animal { public: void speak() { cout << *m_name<<"小貓在說話" << endl; } cat(string name) { m_name =new string(name); } string* m_name; }; void test01() { animal* it = new cat("tom"); it->speak(); delete it; }
在父類子類對象中都打印一些字符會發現,子類的析構函數並沒有調用,說明堆區並沒有釋放干凈,這樣就會造成內存泄露。
這是因為父類指針在析構時並不會調用子類的析構函數,導致子類如果有堆區對象,就會造成內存泄露。
cat類中有堆區屬性,應該在該子類中將其釋放,解決這個問就就需要虛析構
虛析構的語法就是在父類析構函數前加上一個virtual關鍵字,結果:
子類的析構函數已調用。
以上就是利用父類指針解決子類對象時釋放不干凈的問題
純虛析構
純虛析構需要有什聲明,也需要有具體 的實現;
有了純虛析構后這個類也屬於抽象類,無法實例化對象;
#include<iostream> #include<string> using namespace std; class animal { public: animal() { cout << "animal構造函數已調用" << endl; } //virtual ~animal() //虛析構 虛析構與純虛析構只能存在一個 //{ // cout << "animal析造函數已調用" << endl; //} virtual ~animal() = 0; //純虛析構聲明 virtual void speak() = 0; }; animal::~animal() //純虛析構具體實現 { cout << "animal純虛析構已調用" << endl; }; class dog : public animal { public: void speak() { cout << "小狗在說話" << endl; } }; class cat : public animal { public: void speak() { cout << *m_name<<"小貓在說話" << endl; } cat(string name) { cout << "cat構造函數已調用" << endl; m_name =new string(name); } ~cat() { if (m_name != NULL) { cout << "cat析構函數已調用" << endl; delete m_name; m_name = NULL; } } string* m_name; }; void test01() { animal* it = new cat("tom"); it->speak(); delete it; } int main() { test01(); system("pause"); }