大家好,又见面了,我是你们的朋友全栈君。
1、为什么要使用虚析构函数
我们知道析构函数是在对象生命周期结束时自动被调用,用来做一些清理工作(如释放句柄,释放堆内存等),防止出现内存泄漏。
那怎么还有虚析构函数呢?
使用虚析构函数的类一般是要作为基类,被其他类继承。通过把基类的析构函数声明为虚函数,就可以通过父类指针来释放子类对象,从而完成子类的一些清理工作,防止出现内存泄漏。
案例1:基类析构函数为非虚函数
//test.h
class Parent
{
public:
Parent();
~Parent();
private:
int *p_ptr;
};
class Child : public Parent
{
public:
Child();
~Child();
private:
int *c_ptr;
};
//test.cpp
#include "test.h"
#include <iostream>
using namespace std;
Parent::Parent()
{
p_ptr=new int;
*p_ptr=10;
}
Parent::~Parent()
{
cout << "Parent::~Parent() was called." << endl;
if(p_ptr != 0)
{
delete p_ptr;
p_ptr=0;
}
}
Child::Child()
{
c_ptr=new int;
*c_ptr=20;
}
//main.cpp
#include "test.h"
void func(Parent *parent)
{
delete parent;//通过父类指针来释放子类对象
}
int main(int argc, char *argv[])
{
Child *child=new Child;
func(child);
return 1;
}
运行结果:
Parent::~Parent() was called.
结论:父类析构函数为非虚函数时,通过父类指针来释放子类对象时,只会调用父类的析构函数,而不会调用子类的析构函数,造成了子类的内存泄漏。所以,应该将父类的析构函数声明为虚函数。
案例2:父类的析构函数为虚函数
其他文件不用动,只需修改test.h,将父类的析构函数声明为虚函数。
//test.h
class Parent
{
public:
Parent();
virtual ~Parent();//虚析构函数
private:
int *p_ptr;
};
class Child : public Parent
{
public:
Child();
~Child();
private:
int *c_ptr;
};
运行结果:
Child::~Child() was called.
Parent::~Parent() was called.
结论:只有将父类的析构函数声明为虚析构函数时,通过父类指针释放子类对象时,会先调用子类的析构函数,然后调用父类的析构函数,不存在内存泄漏问题。
2、纯虚析构函数
通过上面的虚析构函数知道,C++基类的析构函数最好声明为虚机构函数,那什么时候声明为纯虚析构函数呢?
我们知道,带有纯虚函数的类为抽象类,不能被实例化,只能被子类继承,所以当我们设计一个基类为抽象类时,可以把析构函数声明为纯虚析构函数,这样基类就是抽象类了。
注意:纯虚析构函数也要有函数体,用来做一些基类的清理工作,防止基类出现内存泄漏。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/149850.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...