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

C 11中带有虚拟成员的虚拟析构函数

辛龙野
2023-03-14

在这些关于C 11/14标准的幻灯片中,在幻灯片15中,作者写道,“许多经典的编码规则不再适用于C 11中”。他提出了三个示例的列表,我同意三法则和内存管理。

然而,他的第二个例子是“具有虚拟成员的虚拟析构函数”(仅此而已)。这是什么意思?我知道必须将基类析构函数声明为虚拟,以便调用正确的析构函数,如果我们有类似的东西

Base *b = new Derived;
...
delete b;

这里很好地解释了:什么时候使用虚拟析构函数?

但是,如果您有虚拟成员,现在在C 11中声明虚拟析构函数是无用的吗?

共有3个答案

宰父正真
2023-03-14

链接的论文显示了相关代码

std::unique_ptr<Derived> { new Derived };

存储的删除器是< code>std::default_delete

<罢工> 现在你可以了 把这个移到一个 unique_ptr

裴俊智
2023-03-14

我认为这与演示文稿其他地方提到的“零规则”有关。

如果您只有自动成员变量(即对否则将是原始指针的成员使用 shared_ptrunique_ptr),那么您不需要编写自己的复制或移动构造函数或赋值运算符 - 编译器提供的默认值将是最佳的。使用类内初始化,也不需要默认构造函数。最后,你根本不需要编写析构函数,无论是否虚拟。

董砚
2023-03-14

作为幻灯片的作者,我将努力澄清。

如果您编写的代码显式地分配带有new派生实例并使用基类指针使用删除销毁它,那么您需要定义一个虚拟析构函数,否则您最终会不完全销毁派生实例。但是,我建议放弃new完全删除并使用独占shared_ptr来引用堆分配的多态对象,例如

shared_ptr<Base> pb=make_shared<Derived>();

这样,即使< code>shared_ptr

unique_ptr

我提出的个人建议是为了易于遵循,并且一起遵循。他们试图通过让所有资源管理都由库组件和编译器生成的代码来完成,从而生成更简单的代码。

在类中定义一个(虚拟)析构函数,将禁止编译器提供的移动构造函数/赋值运算符,也可能禁止未来版本的C中编译器提供的复制构造函数/赋值操作符。使用=default可以很容易地重新更正它们,但看起来仍然像很多样板代码。最好的代码是你不必写的代码,因为它不会错(我知道这条规则还有例外)。

总结“不要定义(虚)析构函数”作为我的“零规则”的推论:

每当在现代 C 中设计多态 (OO) 类层次结构并希望/需要在堆上分配其实例并通过基类指针访问它们时,请使用make_shared

这并不意味着您必须分配堆上的所有多态对象。例如,定义一个采用(Base

在我看来,动态OO多态在许多系统中被严重过度使用。当我们使用C时,我们不应该像Java那样编程,除非我们有问题,其中具有堆分配对象的动态多态是正确的解决方案。

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

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

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

  • 每个人都知道基类的分解器通常必须是虚拟的。但是派生类的析构函数是什么?在 C 11 中,我们有关键字“override”,并且能够显式使用默认析构函数。 在子类的析构函数中同时使用关键字“覆盖”和“=默认”是否正确?在这种情况下,编译器会生成正确的虚拟析构函数吗? 如果是,那么我们是否可以认为这是好的编码风格,我们应该总是这样声明派生类的析构函数,以确保基类析构函数是虚的?

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

  • 注意:本文档已失效,请浏览 Istio 官方文档。本书中的 Service Mesh 章节已不再维护,请转到 istio-handbook 中浏览。 该示例跨越 Kubernetes 集群和一组虚拟机上部署 Bookinfo 服务,描述如何使用 Istio service mesh 将此基础架构以单一 mesh 的方式操控。 注意:本文档还在建设中,并且只在 Google Cloud Platfo