专业编程基础技术教程

网站首页 > 基础教程 正文

C++:虚析构与纯虚析构 虚析构函数可以被继承吗

ccvgpt 2024-11-12 09:53:27 基础教程 6 ℃

23.效率与安全

23.1 析构顺序

C++:虚析构与纯虚析构 虚析构函数可以被继承吗

类的继承中讲到实例化派生类的对象不仅会调用派生类的构造函数也会调用基类的构造函数,调用顺序是先基类后派生类。那么当析构派生类的对象时会不会调用基类的析构函数呢?下面来看一个例子。

上图中定义了一个基类Base和派生类Derive,在main函数中派生类的指针指向动态创建的派生类对象,创建之后就析构掉这个对象。运行后结果如下:

上图中可以看到析构派生类对象时,先调用了派生类的析构函数,然后调用了基类的析构函数,析构函数的调用顺序与构造函数的调用顺序正好相反。

23.2 虚析构

同样是上面的例子,如果main函数中的指针是基类类型的指针,结果如何呢?

运行之后我们看到只调用了基类的析构函数,而派生类的析构函数没有被调用。这会造成一个严峻的问题:内存泄露!我们真正想删除的是一个派生类对象,而实际上只是删除了派生类对象中基类的那一部分。如果派生部分有一些需要释放的资源,那么这些资源将无法得到释放。

为什么会这样?

上面delete的是Base类的指针,由于Base类的析构函数不是虚函数,所以就没有调用派生类的析构函数!

所以如果类用作派生类的基类,最好定义其析构函数为虚函数。

现在我们把Base类的析构函数改为虚函数试试看:

运行之后结果令人满意的分别调用了派生类和基类的析构函数。

23.3 纯虚析构

纯虚函数是一种特殊的虚函数,如果在基类中不能对虚函数给出有意义的实现,就可以它声明为纯虚函数,把它的实现留给该基类的派生类去做。

含有纯虚函数的类称为抽象类,不能被实例化,只能用作派生类的基类。而派生类只有全部实现了基类的纯虚函数才可以被实例化。

虚析构函数是为了让基类指针可以正确的释放派生类的对象。如果想让基类成为一个抽象类,就需要引入一个纯虚函数。但是如果类的成员简单到只有构造函数和析构函数的情况下怎么声明抽象类呢?有一种选择是把基类的析构函数声明为纯虚析构函数。

上图中基类的析构函数是纯虚函数或抽象函数,这些代码可以正常运行吗?答案是不可以。因为子类没有实现基类的抽象函数,虽然只是一个析构函数。下图中添加了基类纯虚析构函数的实现。

这次代码就可以正常运行了,上图中的基类Base依然是一个抽象类,是不能被实例化的。

如果你写了一个包含纯虚析构的接口类,那也要记得去实现基类的所有纯虚函数包括纯虚析构函数。

最近发表
标签列表