CPP中虚析构函数

析构函数

我们都知道在C++的多类继承体系中的构造函数与析构函数执行顺序相反;

构造函数是从基类到派生类,析构函数是从派生类到基类;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;

class Base {
public:
Base() {
cout << "bsae" << endl;
}
~Base() {
cout << "~bsae" << endl;
}
};

class Derived : public Base {
public:
Derived() {
cout << "Derived" << endl;
}
~Derived() {
cout << "~Derived" << endl;
}
};

int main() {
Derived* p = new Derived();
delete p;
system("pause");
return 0;
}

/************************************/
输出:
bsae
Derived
~Derived
~bsae

虚析构函数

然而在使用多态时,如果不将基类的析构函数置为虚函数,可能会出现内存泄漏情况;

例如,delete指向派生类的基类指针只会调用基类的析构函数,而不会调用到派生类的析构函数,导致派生类资源没有释放干净;

这种情况下不再是动态绑定,变成静态绑定;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
using namespace std;

class Base {
public:
Base() {
cout << "bsae" << endl;
}
~Base() {
cout << "~bsae" << endl;
}
// virtual ~Base() {
// cout << "~bsae" << endl;
// }
};

class Derived : public Base {
public:
Derived() {
cout << "Derived" << endl;
}
~Derived() {
cout << "~Derived" << endl;
}
};

int main() {
Base* p = new Derived();
delete p;
system("pause");
return 0;
}

/************************************/
输出:
bsae
Derived
~bsae
加上virtual后输出:
bsae
Derived
~Derived
~bsae

小扩展

如果是使用派生类指针指向基类实例呐?当然是不行的;

1
2
3
4
5
6
7
int main() {
//语法错误: Base* 类型的值不能用于初始化 Derived* 类型的实体
Derived* p = new Base();
delete p;
system("pause");
return 0;
}

error: invalid conversion from ‘Base’ to ‘Derived’

其它总结

其实上面这个知识点很简单,也是今天面试的一个问题,当时我说基类如果不是虚析构函数会导致调用不到派生类的析构函数。(我是对的 =_=)

但面试官却说是调用不到基类的析构函数,这让我一下慌了,难道自己记错了。(还好没有)

后面想了想,一方面是自己没有回答好,回答问题时没有仔细想好每种分类,脱口就说,估计面试官是想问构造和析构函数的执行顺序的问题的,我应该按照使用多态和不使用多态两个方面分别回答;

另一方面就是以后觉得自己还是要自信点,也不要每次听到“你确定吗”就怀疑自己错了,然后小紧张;

当然,前提还是得把基础知识掌握牢固。

如果错了也就错了,吸取经验,印象还更加深刻。


CPP中虚析构函数
http://example.com/2022/09/30/CPP中虚析构函数/
作者
ZYUE
发布于
2022年9月30日
更新于
2022年9月30日
许可协议