当前位置: 首页 > 知识库问答 >
问题:

我应该将派生类析构函数标记为虚/重写吗?

公西培
2023-03-14

C核心指南包含以下关于虚拟重写最终说明符的建议,特别是与派生类析构函数相关的建议:

如果基类析构函数声明为虚拟,则应避免将派生类析构函数声明为虚拟或重写。某些代码库和工具可能会坚持重写析构函数,但这不是这些准则的建议。

果然,clang-tidy是违反建议的工具之一。如果我没有指定虚拟覆盖,运行clang-tidy会发出以下警告:

warning: annotate this function with 'override' or (rarely) 'final' [modernize-use-override]

或者,如果仅指定为virtual

warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]

特别是,指定<code>override</code>的优点是(至少)确保正确地将基类析构函数指定为<code>virtual</code>,我的问题归结为以下特定部分:

  1. 如果有,支持不在派生类析构函数上指定virtualoverride的参数是什么
  2. 在您看来,我应该更倾向于clang-st整洁建议,还是更倾向于C核心指导原则建议

共有1个答案

窦啸
2023-03-14
  1. 如果有的话,支持不指定…覆盖派生类析构函数的参数是什么?

有些不符合标准的编译器在使用 override: https://msdn.microsoft.com/en-us/library/xfzxhe2a.aspx 指定析构函数时无法编译。

    < li >支持不指定< code>virtual的理由是什么...在派生类析构函数上[当它是虚隐式的时候]?

代码越少越好。通过不使用冗余虚拟,可以节省7个字符。

  • 反参数:7个字符并不是一个很大的节省。

可能会有一个设计决策,将一个基类及其所有子类的先前虚拟析构函数变为非虚拟的。如果严格遵循这个准则(不指定冗余虚拟),那么只需要修改基本。否则,层次结构中的每个孩子都必须被修改(或者至少检查它们是否单独指定虚拟)。

  • 反驳论点:这可能是一个完全假设的情况。当然相当罕见。

在我看来,唯一有重要意义的论点是旧Visual Studio编译器的不一致性,因此我在析构函数上不使用覆盖方面犯了错误。否则,这没什么大不了的,您可以遵循您喜欢的任何准则,或者甚至不用费心遵循任何一个准则——当手头的主题没有区别时,一致性并不重要。

 类似资料:
  • 当派生类不是立即派生,而是从已经派生的类派生时,我对覆盖函数感到困惑。 在这两种情况下,都调用了最派生的析构函数。我想知道是否只需要大多数基类有一个声明为虚拟的析构函数,在这种情况下,从它继承的所有其他类都有虚拟析构函数,覆盖上游的所有其他析构函数,如果你明白我的意思的话。 我不确定我是否有意义,基本上,如果我有一系列10个类,每个类都从上一个继承,那么链中的任何析构函数都会覆盖所有比它更基础的析

  • 给定一个具有一些虚函数的基类,有人能想出一种方法来强制派生类在编译时重写一组虚函数中的一个吗?或者是实现相同目标的类层次结构的另一种提法? 代码中: 我不确定我真的有一个实际的用例,但是当我实现一些松散地遵循这个模式的东西时,我想到了这个问题,并且认为这是一个有趣的问题,需要思考。

  • 我最近在读虚函数和虚析构函数,下面的问题引起了我的兴趣。 例如,我有以下继承链。 我知道基类的虚函数在派生类中默认是隐式虚的。所以,我认为这同样适用于析构函数。 我想知道,派生类的析构函数是否默认是虚拟的。如果没有,如果您提供一些解释,我将很高兴。

  • 问题内容: 在Java中,您可以将method标记为final,以使其 无法 覆盖。 在C#中,您必须将方法标记为虚方法,以使其 能够 被覆盖。 这是否意味着在C#中您应该将所有方法标记为虚拟方法(除了一些您不想被覆盖的方法之外),因为您很可能不知道可以用什么方式继承您的类? 问题答案: 在C#中,您必须将方法标记为虚方法,以使其能够被覆盖。这是否意味着在C#中您应该将所有方法标记为虚拟方法(除了

  • 为什么一个虚函数在派生类中默认是虚的,甚至不可能在派生类中完全移除虚性,这有什么好的理由吗? 我希望这种行为的原因与我不希望默认情况下每个函数都是的原因相同。编译器可能会生成牺牲性能的vtables。 基类应该有一个vtable(我想要多态性在那里),但派生类没有vtable(我不希望多态性在那里,为什么我要那样,只是因为它派生了一个具有多态性的类?)。 我想解决的问题是更好地理解虚函数。我只是没

  • 和构造函数类似,析构函数也不能被继承。与构造函数不同的是,在派生类的析构函数中不用显式地调用基类的析构函数,因为每个类只有一个析构函数,编译器知道如何选择,无需程序员干涉。 另外析构函数的执行顺序和构造函数的执行顺序也刚好相反: 创建派生类对象时,构造函数的执行顺序和继承顺序相同,即先执行基类构造函数,再执行派生类构造函数。 而销毁派生类对象时,析构函数的执行顺序和继承顺序相反,即先执行派生类析构