虚析构的诞生原因:
当父类指针指向子类的时候,如果父类不写成虚析构,子类的析构函数调不了,在堆区开辟的内存无法释放。
如下代码红色部分不是虚析构。
1 class Animal 2 { 3 public: 4 Animal() { 5 cout << "Animal的构造函数的调用" << endl; 6 } 7 virtual void speak() = 0; 8 // 利用虚析构可以解决父类指针释放子类对象不干净的问题 9 ~Animal() { 10 cout << "Animal的析构函数的调用" << endl; 11 } 12 /*virtual ~Animal() = 0;*/ 13 }; 14 15 16 //Animal:: ~Animal() { 17 // 18 // cout << "Animal的纯虚析构函数的调用" << endl; 19 // 20 //} 21 22 23 24 25 class Cat :public Animal 26 { 27 public: 28 Cat(string name) { 29 cout << "Cat的构造函数的调用" << endl; 30 m_Name = new string(name); 31 32 33 } 34 virtual void speak() { 35 cout << *m_Name << "小猫在说话" << endl; 36 } 37 ~Cat() { 38 if (m_Name != NULL) { 39 cout << "Cat的析构函数的调用" << endl; 40 delete m_Name; 41 m_Name = NULL; 42 } 43 } 44 45 string * m_Name; 46 }; 47 48 void test01() { 49 Animal * animal = new Cat("TOM"); 50 animal->speak(); 51 delete animal; 52 } 53 54 55 int main() { 56 test01(); 57 58 59 return 0; 60 }
编译结果:
可以看到子类cat的析构函数并未调用。
改进后代码:
#include<iostream> using namespace std; #include<string> class Animal { public: Animal() { cout << "Animal的构造函数的调用" << endl; } virtual void speak() = 0; // 利用虚析构可以解决父类指针释放子类对象不干净的问题 virtual ~Animal() { cout << "Animal的析构函数的调用" << endl; } }; class Cat :public Animal { public: Cat(string name) { cout << "Cat的构造函数的调用" << endl; m_Name = new string(name); } virtual void speak() { cout << *m_Name << "小猫在说话" << endl; } ~Cat() { if (m_Name != NULL) { cout << "Cat的析构函数的调用" << endl; delete m_Name; m_Name = NULL; } } string * m_Name; }; void test01() { Animal * animal = new Cat("TOM"); animal->speak(); delete animal; } int main() { test01(); return 0; }
运行结果:
父类可能也有一些数据开辟到堆区,所以纯虚析构也是需要 函数体的。有了纯虚析构之后,这个类也属于抽象类,无法实例化对象。