首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基类没有析构函数,但派生类有。我是否需要寻找与堆无关的陷阱?

基类没有析构函数,但派生类有。我是否需要寻找与堆无关的陷阱?
EN

Stack Overflow用户
提问于 2016-05-22 02:28:41
回答 3查看 964关注 0票数 2

在继承方面,我知道建议您的类的析构函数是虚拟的,因此除了任何派生析构函数之外,基类的析构函数都会被正确调用。但是,我想知道在下面的场景中是否存在与派生对象相关的堆栈相关问题。

让我们假设我们有一个基类,它没有析构函数(不管出于什么原因):

代码语言:javascript
复制
class Base{};

以及具有析构函数的派生类:

代码语言:javascript
复制
class Derived : public Base
{
  ~Derived(){}
};

总的来说.

代码语言:javascript
复制
int main()
{
  Derived a;
  return 0;
}

我是否遇到基类中没有析构函数的任何问题?我最初的猜测是,编译器只会为基类生成一个默认析构函数。同样,我的问题主要与堆栈有关,而不是动态内存:为了避免调用派生析构函数而不调用基析构函数,我需要注意哪些奇怪的场景?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-22 02:32:25

基类有一个隐式析构函数。一切都会好的。

虚拟基类析构函数用于在通过指针或对基类的引用进行析构时允许派生构造函数运行。所以在你的情况下,这是不安全的:

代码语言:javascript
复制
void destruct(Base &b) { b.~Base(); }
Derived d; destruct(d);

但这绝对是安全的:

代码语言:javascript
复制
void destruct(Derived &d) { d.~Derived(); }
Derived d; destruct(d);
票数 1
EN

Stack Overflow用户

发布于 2016-05-22 02:36:17

您正在考虑的规则是,如果通过指向其基类型之一的指针删除派生类型的对象,并且该基类型没有虚拟析构函数,则行为是未定义的。这里的代码没有删除任何内容,所以规则不适用。

票数 2
EN

Stack Overflow用户

发布于 2016-05-22 03:56:43

为确保安全,每个析构函数(隐式或显式)至少必须是下列之一:

  • virtual (对于基类,如果需要通过基类指针删除子类实例)
  • protected (以确保不可能尝试通过基类指针删除)
  • final (实际上是类的一个属性,以避免子类的全部可能性)。

有几种罕见的边缘情况,可以安全地调用析构函数,但它们通常是糟糕设计的标志,而且如果您设法跨越其中之一,则很容易避免。

顺便提一句,请注意std::shared_ptr类型会擦除它的删除器,所以即使Base没有公共析构函数,Base也会工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37369945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档