虚析构的诞生原因:
当父类指针指向子类的时候,如果父类不写成虚析构,子类的析构函数调不了,在堆区开辟的内存无法释放。

 如下代码红色部分不是虚析构。

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;
}

运行结果:

虚析构和纯虚析构_析构函数_02

 

父类可能也有一些数据开辟到堆区,所以纯虚析构也是需要 函数体的。有了纯虚析构之后,这个类也属于抽象类,无法实例化对象。