【问题标题】:Destructor of a concrete class具体类的析构函数
【发布时间】:2009-11-10 21:02:51
【问题描述】:

指南 #4 link text,声明:

基类析构函数应该是 公共和虚拟的,或者 受保护且非虚拟。

可能我遗漏了一些东西,但是如果我只是创建一个具体的类,而不是被设计为用作基类。

我应该声明它是公共的和虚拟的析构函数吗?通过这一点,我隐含地声明我的类“已准备好用作基类”,虽然这不是必须的。

【问题讨论】:

  • 如果您“只是创建一个具体类”而不将其用作“基类”,则此指导方针不适用,因为……嗯……它不是基类。 ;-)

标签: c++ virtual-destructor


【解决方案1】:

链接文本明确表示“基类析构函数应该是”...

指南仅适用于设计用作基类的类。如果您正在创建一个不会用作基类的单个具体类,则应将公共构造函数保留为非虚拟的。

【讨论】:

    【解决方案2】:

    如果你的类中没有其他东西是虚拟的,我认为析构函数也不应该是虚拟的。

    【讨论】:

      【解决方案3】:

      换一种方式考虑:你知道没有人绝对会尝试从你的课程中派生,当有人这样做时,你认为他会记得仔细看看你的 dtor 吗?有时人们出于充分的理由使用继承而不是组合(提供类的完整接口而没有丑陋的 getter 语法)。
      虚拟 dtor 的另一点是 Open/Closed Principle
      如果您不关心硬实时性能或类似的东西,我会选择虚拟 dtor。

      【讨论】:

        【解决方案4】:

        在以下任何情况下,析构函数应为虚拟:

        • 您的类包含 ANY 虚拟方法。
        • 即使没有什么是虚拟的,您也打算使用类作为基础。

        罕见的例外

        • 您正在尝试保存 4 个字节,因此虚拟表指针不是可接受的解决方案(例如 - 由于某种原因,您的类必须适合 32 位)。但要为地狱做好准备。

        关于公共或受保护 - 通常更多的问题是您打算如何控制对析构函数的访问。

        【讨论】:

        • 异常 2:类上的 new 运算符是私有的。 -- 基于堆栈的对象不能被切片而不导致其他错误。
        • +1 对“新”运算符的评论,但我对这个猴子把戏没有真正的经验。你能指出更详细的解释/例子吗?
        • 基于堆栈的对象不能以调用错误的析构函数结束,句号。如果您从堆栈上的派生类对象构造基类对象,则仍将为该堆栈对象调用派生析构函数(如果基类对象也是基于堆栈的,则将为基类对象调用基析构函数)。即使将临时对象绑定到引用也可以正常工作:const Base &b = Derived(params);,当 b 离开作用域时,派生的析构函数将在临时对象上调用,无论其中一个析构函数是否是虚拟的。
        【解决方案5】:

        如果你的类稍后会被扩展,你的析构函数只需要是虚拟的。我不知道您需要受保护/私有析构函数的情况。

        值得注意的是,即使您有 一个 虚拟方法,也不会丢失任何东西(对于大多数编译器),使析构函数也是虚拟的(但它会保护您,以防有人稍后扩展)。

        【讨论】:

        • "你的析构函数只需要是虚拟的,如果它稍后会被扩展。"这实际上是错误的。当派生类的对象将通过基类指针删除时,dtor 应该是虚拟的。不这样做会产生未定义的行为,无论派生类的 dtor 是用户定义的还是编译器生成的。
        • @sbi:“扩展”通常意味着“源自”,所以我在这里没有看到任何分歧。如果将派生一个类,我希望它有时会以多态方式使用,然后需要一个虚拟析构函数。如果不是,则不能多态使用,也不需要虚拟析构函数。
        • @sbi:我看到我的措辞有点混乱。我并不是说如果基类提供了显式的 dtor,我的意思是类本身是扩展的。我将编辑我的答案以反映这一点。谢谢。
        【解决方案6】:

        建议指的是具有虚函数的类,旨在成为多态基类。您必须确保如果有人在基类指针上调用delete,则调用实际类的析构函数;否则,派生类分配的资源不会被释放。

        有两种方法可以实现:

        • 一个公共的虚拟析构函数,所以在运行时可以找到正确的析构函数;或
        • 受保护的非虚拟析构函数,可防止在基类指针上调用 delete

        对于不会用作基类的具体类,您只会在指向实际类型的指针上调用delete,因此该建议不适用。如果需要,它应该有一个公共的非虚拟析构函数。

        【讨论】:

          猜你喜欢
          • 2018-06-29
          • 1970-01-01
          • 2017-05-15
          • 2018-09-17
          • 2019-03-04
          • 2021-09-14
          • 1970-01-01
          • 2011-06-12
          • 2014-05-27
          相关资源
          最近更新 更多