C.35: A base class destructor should be either public and virtual, or protected and nonvirtual

基类的析构函数要么是公开的虚函数,要么是保护的非虚函数

Reason(原因)

To prevent undefined behavior. If the destructor is public, then calling code can attempt to destroy a derived class object through a base class pointer, and the result is undefined if the base class's destructor is non-virtual. If the destructor is protected, then calling code cannot destroy through a base class pointer and the destructor does not need to be virtual; it does need to be protected, not private, so that derived destructors can invoke it. In general, the writer of a base class does not know the appropriate action to be done upon destruction.

为了避免无定义的行为。如果析构函数是公有的,那么调用侧的代码就会尝试使用基类指针销毁派生类的对象,在基类的析构函数为非虚函数时其结果时没有定义的。如果析构函数时保护的,那么调用侧代码就无法通过基类类型指针销毁派生类对象,这是析构函数就没有必要一定是虚函数。析构函数是保护而不是私有的,这样派生类的析构函数才能调用它。通常,基类的设计者不会知道在析构函数中应该执行什么样的动作。

Discussion(讨论)

See this in the Discussion section:参见讨论章节:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Sd-dtor.

Example, bad(反面示例)

struct Base { // BAD: implicitly has a public nonvirtual destructor
virtual void f();
};
struct D : Base {
string s {"a resource needing cleanup"};
~D() { /* ... do some cleanup ... */ }
// ...
};
void use()
{
unique_ptr p = make_unique();
// ...
} // p's destruction calls ~Base(), not ~D(), which leaks D::s and possibly more

Note(注意)

A virtual function defines an interface to derived classes that can be used without looking at the derived classes. If the interface allows destroying, it should be safe to do so.虚函数定义了派生类的接口,它可以在不关注派生类的情况下使用。如果接口允许对象,那么这个销毁过程应该是安全的。

Note(注意)

A destructor must be nonprivate or it will prevent using the type:析构函数必须是非私有的,除了它不想被别人用。(这样可以由类自己控制销毁,译者注)

class X {

~X(); // private destructor
// ...
};
void use()
{
X a; // error: cannot destroy
auto p = make_unique(); // error: cannot destroy
}

Exception(例外)

We can imagine one case where you could want a protected virtual destructor: When an object of a derived type (and only of such a type) should be allowed to destroy another object (not itself) through a pointer to base. We haven't seen such a case in practice, though.我们可以想象一种需要保护的虚函数析构函数的情况:当希望允许派生类的对象(只有这个类型)通过基类指针销毁另外一个对象(不是它自己)时。但是我们还没有在实际的开发中遇到这种情况。

Enforcement(实施建议)

  • A class with any virtual functions should have a destructor that is either public and virtual or else protected and nonvirtual.
  • 拥有虚函数的类的虚函数要么是公开的虚函数,要么是保护的非虚函数。

译者注:拥有虚函数一般就意味着它有派生类。

原文链接:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c35-a-base-class-destructor-should-be-either-public-and-virtual-or-protected-and-nonvirtual


觉得本文有帮助?请分享给更多人。

更多文章请关注微信公众号【面向对象思考】!

面向对象开发,面向对象思考!

unique函数_C++核心准则C.35:基类的析构函数必须满足的条件相关推荐

  1. 析构函数声明无效_C++基类的析构函数为何要声明为虚函数

    C++的类中,构造函数用于初始化对象及相关操作,构造函数是不能声明为虚函数的,因为在执行构造函数前对象尚未完成创建,虚函数表还不存在. 析构函数用于销毁对象完成时相应资源的释放工作,析构函数可以被声明 ...

  2. 为什么基类的析构函数要声明成虚函数

    记得以后基类(父类) 的析构函数最好是声明为 虚函数 即:virtual 开发中遇到了一个比较傻逼的bug,也证明了理论与实际之间的差距. 在基类中没有声明其析构函数为虚函数,导致delete 释放操 ...

  3. 详解虚函数的实现过程之虚基类(4)

    博客虚函数实现过程3 时提到过虚基类,这里呢,我们来详细讲述一下: 当我们在虚函数的声明结尾处添加"=0",这种虚函数就被称为纯虚函数. 它好似一个没有实现只有声明的函数,它的存在 ...

  4. 为什么基类的析构函数是虚函数?

    1.第一段代码 #include<iostream> using namespace std; class ClxBase{ public:ClxBase() {};~ClxBase() ...

  5. 基类的析构函数为什么要设置成virtual

    今天在一场面试过程中碰到这个问题,当时一时片刻没有反应过来,一头雾水.只记得自己回到说,是会造成内存泄露,但面试穷追猛打,一直追问为什么造成内存泄露,还给举例说明,一般情况下是不会造成内存泄露的,搞得 ...

  6. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  7. C++基类的析构函数为什么需要加上virtual关键字

    C++中基类采用virtual虚析构函数是为了防止内存泄漏. 具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放.假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对 ...

  8. c 函数多次声明_C++核心准则C.132:不要没有理由就将函数声明为虚函数

    岫玉 C.132: Don't make a function virtual without reason C.132:不要没有理由就将函数声明为虚函数 Reason(原因) Redundant v ...

  9. modbus软件开发实战指南_C++核心准则?GSL:指南支持库

    GSL: Guidelines support library GSL:指南支持库 The GSL is a small library of facilities designed to suppo ...

最新文章

  1. “stdafx.h”: No such file or directory
  2. Git学习(3)GitHub和SVN的区别
  3. oracle创建多个游标,Oracle——游标的创建和使用
  4. linux下载命令 scp,linux命令详解之scp命令
  5. 人工智障学习笔记——机器学习(11)PCA降维
  6. 长沙学院计算机系课程表,长沙交通学院研究生200—200学年度第学期课程表.doc...
  7. Django ORM 单表操作
  8. Oracle学习之路-- 案例分析实现行列转换的几种方式
  9. ArcGIS中GWR模型的构建
  10. 经典Flash源文件集锦-导航篇
  11. Windows Server2019 安装教程
  12. 灵格斯 Lingoes 2.8 去广告 禁止新词锐词弹窗
  13. 牵引变压器短路阻抗定义及相关参数计算
  14. android 图标删除不了,手机程序卸载之后桌面上残留的图标删除不掉
  15. 2D游戏案例:雷霆战机
  16. 程序员 -- 当我彻底放弃自私自利后,前途变得一片光明,不能过多的只是关注自己的功夫,生活不能只局限在方寸虚拟世界里
  17. 新概念英语第三册51-60课(转)
  18. 2023年最热门的网络安全岗位分析
  19. 美术老师去世后,他做了一个算法模型,为老师的线稿上色
  20. 腾讯的这个框架火了!

热门文章

  1. 多项式拟合lm_R语言多项式回归
  2. libreoffice error while loading shared libraries: libSM.so.6: cannot open shared object
  3. vue PC端国际化一站式解决方案
  4. 负载均衡工具 haproxy 集群安装部署完整流程
  5. v-if v-show区别(面试题)
  6. java map用二叉树_【课堂笔记分享】linkedlist、二叉树、hashmap
  7. ecshop模板中使用php,使ecshop模板中可引用常量的实现方法
  8. android 语音编码,android – 如何将录制的语音编码为ogg vorbis?
  9. android7.0uri,整理: 解决Android7.0以上文件报FileUriExposedException问题
  10. linux下c语言编程gedit,Ubuntu Linux下实现Gedit支持NesC语法高亮