多态基类的析构函数应为虚函数
2016-03-02 00:00
260 查看
小心陷阱
在c++中,当 一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的,运行时比较有代表性的后果是对象的派生部分不会被销毁(tip
: 如果是直接创建一个子类的对象,则基类部分和派生部分都会析构,这里的部分析构是因为子类对象是通过基类指针动态创建的)。然而,基类部分很可能已经被销毁,这就导致了一个奇怪的“部分析构”现象,这是一个资源泄漏的问题。
但是,如果不做基类,析构函数一般不要声明为虚函数,因为虚函数的实现要求对象携带额外信息,并导致类所占用的内存增加。
在继承机制下,把基类的析构函数声明为一个纯虚函数往往是一个明智之兴举。纯虚函数通常没有定义,它们是在抽象类中声明,然后在派生类中实现。
但是,在某些情况下,却需要定义一个纯虚成员函数,而不仅仅 是声明它,最常见的例子是纯虚析构函数。在声明纯虚析构函数时,不要忘了同时还要定义它。(tips
这里注意定义和声明的区别。)
为什么说定义纯虚析构函数非常重要?
(1)派生类的析构函数会自动调用基类的析构函数。这个过程是递归的,最终,抽象类的纯虚析构函数也会被调用。
(2)如果纯虚析构函数只被声明而没有定义,那么会造成运行时崩溃(在很多情况下,这个错误会出现在编译期,但谁也不担保一定会是这样)。纯虚函数的虚拟实现,即空实现能够保证代码的 安全性。
如果一个类被继承,同时定义了基类以外的数据成员对象,且基类析构函数不是virtual修饰的,那么当基类指针或引用指向派生类对象并析构时,会调用基类的析构函数而导致派生类定义的数据成员没有被析构,产生内存泄漏问题。
如果确定不需要直接而是只通过派生类对象使用基类,可以把析构函数定义为protected(这样会导致基类和派生类外使用自动对象和delete时的错误,因为访问权限禁止调用析构函数),就不会导致以上问题的出现。
关于C++中的友元函数的总结 - 博客园 http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/04/2535305.html
注意:一定要注意派生类的对象和派生类中的成员函数对基类的访问是不同的 。+
在c++中,当 一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的,运行时比较有代表性的后果是对象的派生部分不会被销毁(tip
: 如果是直接创建一个子类的对象,则基类部分和派生部分都会析构,这里的部分析构是因为子类对象是通过基类指针动态创建的)。然而,基类部分很可能已经被销毁,这就导致了一个奇怪的“部分析构”现象,这是一个资源泄漏的问题。
但是,如果不做基类,析构函数一般不要声明为虚函数,因为虚函数的实现要求对象携带额外信息,并导致类所占用的内存增加。
在继承机制下,把基类的析构函数声明为一个纯虚函数往往是一个明智之兴举。纯虚函数通常没有定义,它们是在抽象类中声明,然后在派生类中实现。
但是,在某些情况下,却需要定义一个纯虚成员函数,而不仅仅 是声明它,最常见的例子是纯虚析构函数。在声明纯虚析构函数时,不要忘了同时还要定义它。(tips
这里注意定义和声明的区别。)
为什么说定义纯虚析构函数非常重要?
(1)派生类的析构函数会自动调用基类的析构函数。这个过程是递归的,最终,抽象类的纯虚析构函数也会被调用。
(2)如果纯虚析构函数只被声明而没有定义,那么会造成运行时崩溃(在很多情况下,这个错误会出现在编译期,但谁也不担保一定会是这样)。纯虚函数的虚拟实现,即空实现能够保证代码的 安全性。
如果一个类被继承,同时定义了基类以外的数据成员对象,且基类析构函数不是virtual修饰的,那么当基类指针或引用指向派生类对象并析构时,会调用基类的析构函数而导致派生类定义的数据成员没有被析构,产生内存泄漏问题。
如果确定不需要直接而是只通过派生类对象使用基类,可以把析构函数定义为protected(这样会导致基类和派生类外使用自动对象和delete时的错误,因为访问权限禁止调用析构函数),就不会导致以上问题的出现。
关于C++中的友元函数的总结 - 博客园 http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/04/2535305.html
注意:一定要注意派生类的对象和派生类中的成员函数对基类的访问是不同的 。+
相关文章推荐
- 异常处理的设计与重构
- 计算机编程的世界
- 中石化煮酒论英雄
- 《李宗仁回忆录》完整版在线及电子书下载
- 如何设置无线路由器提高迅雷下载速度
- Linux Mint 13 国内源
- 计算机编程的世界
- 中石化煮酒论英雄
- 《李宗仁回忆录》完整版在线及电子书下载
- 最全列表: 80 多个 Linux 系统管理员必备的监控工具
- 如何设置无线路由器提高迅雷下载速度
- Linux Mint 13 国内源
- Linux(Xubuntu)快速正确地安装 Ruby, Rails 环境
- OpenDNS
- 视频设备最常见接口介绍
- RedHat Linux 9磁盘分区简介
- 整理书籍等技术资料下载站
- 如何实现DES算法
- 3个科学的理财定律
- 关于微软鼠标和键盘中心安装报错1603的解决方法