C++中的为什么需要虚析构函数

来源:互联网 发布:新天龙八部官方软件 编辑:程序博客网 时间:2024/06/01 12:03

让我们先看一个简答的例子:

#include <iostream>using namespace std;class Fish{public:   Fish()   {      cout << "Constructed Fish" << endl;   }   ~Fish()   {      cout << "Destroyed Fish" << endl;   }};class Tuna:public Fish{public:   Tuna()   {      cout << "Constructed Tuna" << endl;   }   ~Tuna()   {      cout << "Destroyed Tuna" << endl;   }};void DeleteFishMemory(Fish* pFish){   delete pFish;}int main() {    cout << "Allocating a Tuna on the free store:" << endl;   Tuna* pTuna = new Tuna;   cout << "Deleting the Tuna: " << endl;   DeleteFishMemory(pTuna);   cout << "Instantiating a Tuna on the stack:" << endl;   Tuna myDinner;   cout << "Automatic destruction as it goes out of scope: " << endl;   return 0;}

读者可以直接复制代码试试看,运行结果如下:
运行结果

主函数中,我们使用new在自由存储区创建了一个实例,然后马上使用辅助函数DeleteFishMemory释放分配的内存,处于比较目的,我们在后面创建了一个Tuna实例–局部变量myDinner,main()结束时,他将不再作用域内,输出的是Fish和Tuna的构造函数和析构函数中的cout语句,注意到使用关键字new,在自由存储区构造了Tuna和Fish,但是delete没有调用Tuna的析构函数么只是调用了Fish的析构函数,这与myDinner的构造与析构形成了鲜明的对比。

以上结果表明,对于使用new在自由存储区中实例化派生类对象,如果将其赋给基类指针,并通过该指针调用delete,将不会调用派生类的析构函数,这可能导致资源未释放,内存泄漏等问题。

解决办法很简单,如标题所言,将析构函数声明为虚函数即可:

`
virtual ~Fish()
{
cout << "Destroyed Fish" << endl;
}
我们在看看运行结果:
这里写图片描述
`
可以看到多了一行:Destroyed Tuna。(注意构造和析构的调用顺序不一样)。
虽然上面不是一个大问题(编译能通过),但是编写高质量的c++程序还是需要注意的。

参考书籍 Sams Teach Yourself C++ in One Hour a Day(* chapter 11*

0 0
原创粉丝点击