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

虚拟析构函数的默认重写

蔺翰音
2023-03-14

每个人都知道基类的分解器通常必须是虚拟的。但是派生类的析构函数是什么?在 C 11 中,我们有关键字“override”,并且能够显式使用默认析构函数。

struct Parent
{
  std::string a;
  virtual ~Parent()
  {
  }

};

struct Child: public Parent
{
  std::string b;
  ~Child() override = default;
};

在子类的析构函数中同时使用关键字“覆盖”和“=默认”是否正确?在这种情况下,编译器会生成正确的虚拟析构函数吗?

如果是,那么我们是否可以认为这是好的编码风格,我们应该总是这样声明派生类的析构函数,以确保基类析构函数是虚的?

共有3个答案

邴修远
2023-03-14

根据CppCoreGuidelines C.128,派生类的析构函数不应声明为< code>virtual或< code>override。

如果基类析构函数被声明为虚拟的,应该避免将派生类析构函数声明为< code>virtual或< code>override。一些代码库和工具可能坚持重写析构函数,但这不是这些指南的建议。

更新:回答为什么我们对析构函数有特殊情况的问题。

方法重写是一种语言特性,它允许子类或子类提供一种方法的特定实现,这种方法已经由它的一个超类或父类提供了。子类中的实现通过提供与父类中的方法具有相同名称、相同参数或签名以及相同返回类型的方法来覆盖(替换)超类中的实现。

换句话说,当您调用重写的方法时,实际上只执行该方法的最后一个实现(在类层次结构中),而必须调用所有析构函数(从最后一个子级到根父级)才能正确释放对象拥有的所有资源。

因此,我们并没有真正替换(覆盖)析构函数,我们只是在对象析构函数链中增加了一个析构函数。

更新:此CppCoreGuidelines C.128规则被修改(14481446期),以简化已经详尽的例外列表。因此,一般规则可以概括为:

对于类用户来说,包括析构函数在内的所有虚函数都是同样多态的。

在拥有状态的子类上标记析构函数覆盖是教科书式的卫生,你们都应该按照例行公事(参考文献)来做。

阎宾实
2023-03-14

覆盖只不过是一个安全网。如果基类析构函数是虚拟的,则子类的析构函数将始终是虚拟的,无论它如何声明 - 或者根本不声明(即使用隐式声明的析构函数)。

惠洛华
2023-03-14

在子类的析构函数中同时使用关键字“覆盖”和“=默认”是否正确?在这种情况下,编译器会生成正确的虚拟析构函数吗?

是的,这是正确的。在任何一个正常的编译器上,如果代码编译没有错误,这个析构函数定义将是一个空操作:它的缺失不能改变代码的行为。

我们能认为这是好的编码风格吗

这是个人喜好的问题。对我来说,只有当基类类型被模板化时才有意义:它会强制要求基类有一个虚析构函数。否则,当基本类型固定时,我会认为这样的代码是噪音。好像基类不会神奇地改变。但是如果你有一些顽固的队友,他们喜欢在不检查代码的情况下修改东西,这取决于他们可能破坏了什么,那么最好保留析构函数的定义——作为额外的一层保护。

 类似资料:
  • 在C 11中,我们能够声明一个析构函数是自动生成的: 此外,我们可以将析构函数声明为纯虚: 我的问题是:如何将析构函数声明为自动生成和纯虚拟?看起来以下语法不正确: 这一个也不是: 也不是这个: 编辑:关于问题目的的一些澄清。基本上,我希望一个空类是不可实例化的基类,但派生类是可实例化的,那么该类必须有一个纯虚拟析构函数。但另一方面,我不想在.cpp文件中提供定义。因此,我需要某种与等效的机制。我

  • 我一直在使用越来越多的C11,我遇到了一些我在任何地方都找不到的东西。当我们从基指针中删除派生类时,我们需要有虚拟析构函数;但有时父析构函数需要“纯”,这在C中是不可能的。所以,我的问题是,默认值是否可以用于虚拟析构函数?我已经试过了,而且效果不错,但我不知道它是否安全,因为互联网上没有任何关于它的信息。 编辑:为了澄清这个问题,我说的是使用

  • 我读过一些文章,正如他们所说,主要的虚拟析构函数用例是: > 派生类可能具有来自堆的动态数据分配,即“拥有”该数据对象。所以,他们需要在析构函数中使用一些删除例程。通过基类指针删除需要在所有派生类中声明析构函数,直到那些具有动态数据分配的析构函数(基类也需要它) 此类具有< code >虚拟方法。但这对我来说不清楚。仅仅通过基类指针调用< code >虚拟方法总是会导致派生实现最多的调用。他们唯一

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

  • 在这些关于C 11/14标准的幻灯片中,在幻灯片15中,作者写道,“许多经典的编码规则不再适用于C 11中”。他提出了三个示例的列表,我同意三法则和内存管理。 然而,他的第二个例子是“具有虚拟成员的虚拟析构函数”(仅此而已)。这是什么意思?我知道必须将基类析构函数声明为虚拟,以便调用正确的析构函数,如果我们有类似的东西 这里很好地解释了:什么时候使用虚拟析构函数? 但是,如果您有虚拟成员,现在在C

  • 我理解,只要你有一个多态基类,基类就应该定义一个虚拟析构函数。因此,当删除指向派生类对象的基类指针时,它将首先调用派生类的析构函数。如果我错了,请纠正我。 此外,如果基类析构函数是非虚拟的,那么删除指向派生对象的基类指针将是未定义的行为。如果我错了也纠正我。 所以我的问题是:为什么当基类析构函数非虚拟时,对象不会被正确销毁? 我假设这是因为虚拟函数具有某种表,每当调用虚拟函数时都会记住和查阅该表。