【问题标题】:If the destructor of a subclass was called, can I stop the call to the destructor of its base class?如果调用了子类的析构函数,我可以停止调用其基类的析构函数吗?
【发布时间】:2016-08-18 09:10:58
【问题描述】:

我遇到了一些奇怪的代码,如下所示:

class B {
    int* ab;
    ///...
    ~B() { /// not virtual
        delete ab;
    }
    ///...
}

class D : public B {
    int* ad;
    ///...
    ~D() {
        delete ab;
        delete ad;
    }
    ///...
}

但在我看来,子类的析构函数肯定会调用其基类的析构函数。所以,我认为子类没有必要释放其基类分配的资源。因此,不需要在类D 的析构函数中添加delete ab。更糟糕的是,delete 一个对象两次是错误的。

但是,这段代码在我们的系统中运行良好很长时间,并且通过了我们的整个测试用例。在这种奇怪的实现中还有其他考虑吗?

所以我徘徊,如果子类的析构函数被调用,那么,无论发生什么,基类的析构函数都会被调用。
或者,子类的析构函数执行后,有什么办法可以停止基类的析构函数的执行?

【问题讨论】:

  • ~B~D 之后调用。此代码有一个错误,即ab 被删除了两次。 (如果删除了D,即)
  • 编译时错误或运行时错误?因为它有效。@M.M
  • @YuanWen:不,它不起作用。如果你不走运,它可能会出现。
  • 但是在我们的实践中,它运行良好,你知道为什么吗?代码是别人写的。@LightnessRacesinOrbit

标签: c++ destructor


【解决方案1】:

如果 D 实例被破坏,则将调用 B 类析构函数是正确的。在D dtor 中调用delete ab; 是一个错误。

使用此代码要考虑的另一件事是,因为 B 的 dtor 不是虚拟的,所以您不能通过 B 指针删除 D 的实例。

D 的 DTOR 在这两种情况下都是不正确的,并且绝对应该更改。如果您打算多态地使用类的层次结构,那么您还必须将 B DTOR 更改为虚拟。

【讨论】:

  • 哦,你的意思是如果调用了子类的析构函数,那么它的基类的析构函数也会被调用?@Dennis
  • @YuanWen 对象的破坏是通过调用其析构函数然后以相反的构造顺序破坏其成员和基类来实现的
  • 不管基类的析构函数是不是虚的?@Dennis
  • @YuanWen 是的,不管dtor的虚拟声明。 dtor 上的 virtual 允许您删除派生类通过基类引用。
  • @YuanWen 你真的需要自己做一些研究。互联网上有 100 篇关于这个主题的文章,仅关于 SO 的问题就有数十个以某种方式处理这个主题。标准上的 ctrl+f 将显示您想要的内容。
猜你喜欢
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
相关资源
最近更新 更多