虚析构和纯虚析构
原创
©著作权归作者所有:来自51CTO博客作者LovewiShare的原创作品,请联系作者获取转载授权,否则将追究法律责任
虚析构的诞生原因:
当父类指针指向子类的时候,如果父类不写成虚析构,子类的析构函数调不了,在堆区开辟的内存无法释放。
如下代码红色部分不是虚析构。
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;
}
运行结果:
父类可能也有一些数据开辟到堆区,所以纯虚析构也是需要 函数体的。有了纯虚析构之后,这个类也属于抽象类,无法实例化对象。