C++易错知识点(十一)虚析构函数

  • Post author:
  • Post category:其他


首先来看这样一个场景,观察构造析构的调用析构顺序。

#include<iostream>
using namespace std;
class Parent{
private:
	int a;
public:
	Parent() { cout<<"Parent()"<<endl; }
	~Parent() { cout<<"~Parent()"<<endl; }
};
class son :public Parent {
private:
	int b;
public:
	son() { cout<<"son()"<<endl; }
	~son() { cout<<"~son()"<<endl; }
};
int main()
{
	son* p = new son;
	delete p;
	return 0;
}

最后我们发现构造函数,析构函数的调用是正常情况,符合我们意料之中。

在这里插入图片描述

那么现在如果把main()函数当中的

son* p = new son;

语句改成

Parent* p = new son;

呢?

运行结果如下:

在这里插入图片描述

结果我们发现少了son类的析构。

这样肯定是不行的,现在我们来分析背后的原因,好提出解决办法:

1)一个子类的堆对象被父类指针指向了

2)使用delete p内部的工作过程是先调用对应的析构函数。然后释放p申请的内存。即

p->Parent();

然后

free(p)


分析到这里情况应该比较明确了,因为该子类的堆对象被父类指针指向了,delete时会先调用父类的析构函数,然后直接释放内存,而不会去调用子类析构函数。


解决方法就是将父类子类的析构函数都声明为虚函数


在这里插入图片描述

可以看出,虚析构函数可以解决上文发现的问题。事实上将虚构函数声明为虚函数以后,

p->Parent()

这一步就变成了虚函数的间接调用,会查找虚表,调用子类对象本身的虚构函数。



版权声明:本文为weixin_42445051原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。