【问题标题】:base destructor called twice after derived object?派生对象后调用两次基本析构函数?
【发布时间】:2010-06-05 12:50:17
【问题描述】:

嘿,为什么在这个程序结束时基析构函数被调用了两次?

#include <iostream>
using namespace std;

class B{
public:
  B(){
    cout << "BC" << endl; x = 0;
  }
  virtual ~B(){
    cout << "BD" << endl;
  }
  void f(){
    cout << "BF" << endl;
  }
  virtual void g(){
    cout << "BG" << endl;
  }
private:
  int x;
};

class D: public B{
public:
  D(){
    cout << "dc" << endl; y = 0;
  }
  virtual ~D(){
    cout << "dd" << endl;
  }
  void f(){
    cout << "df" << endl;
  }
  virtual void g(){
    cout << "dg" << endl;
  }
private:
  int y;
};

int main(){
  B b, * bp = &b;
  D d, * dp = &d;
  bp->f();
  bp->g();
  bp = dp;
  bp->f();
  bp->g();
}

【问题讨论】:

  • 因为有两个基础 obj.. 一个直接 b 另一个包裹在派生 d 中。最后需要摧毁两者。

标签: c++ gcc polymorphism virtual-destructor


【解决方案1】:

按顺序调用析构函数,就好像它们展开相应构造函数的效果。因此,首先是派生对象的析构函数,然后是基础对象的析构函数。并且将析构函数设为虚拟对调用/不调用 基类 析构函数没有任何影响。

另外提一下,您的示例可以这样简化(此代码还导致调用基析构函数两次,派生析构函数调用一次)

struct A {
   ~A() {
      // ...
   }
};

struct B: A {
   ~B() {
      // ...
   }
};

int main() {
   A a;
   B b;
}

【讨论】:

    【解决方案2】:

    b 调用一次,d 调用一次

    注意当D的析构函数被调用时,它会自动调用B的析构函数,它不同于普通的虚函数。您需要显式调用基类函数才能使用它。

    【讨论】:

    • 但是虚拟的 ~D() 被称为给我 dd。为什么它会回去再做一次? (意思是基类)
    • so virtual ~D() 给出 dd 和 BD,然后 virtual ~B() 给出另一个 BD 对吗?抱歉打扰了大声笑:)
    • @sil3nt:如果我正确理解了您的问题/困惑,这是否有帮助:基础析构函数 (BD) 被调用两次,但不是在同一个对象上调用两次。它在 B b 被销毁时调用一次,在 D d 被销毁时调用一次。正如其他人提到的,当 D 被销毁时,基类 B 的析构函数也被自动调用。因此,您会看到 B 析构函数为 2 个不同的对象调用一次,因此调用了 2 次,而不是为一个对象调用了两次。
    猜你喜欢
    • 2014-05-17
    • 2012-08-11
    • 2016-06-28
    • 2021-05-18
    • 2020-04-07
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多