C++ 我是否需要显式调用基本虚拟析构函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/677620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:40:58  来源:igfitidea点击:

Do I need to explicitly call the base virtual destructor?

c++destructor

提问by Nick Bolton

When overriding a class in C++ (with a virtual destructor) I am implementing the destructor again as virtual on the inheriting class, but do I need to call the base destructor?

在 C++ 中覆盖类(使用虚拟析构函数)时,我在继承类上再次将析构函数实现为虚拟,但是我需要调用基析构函数吗?

If so I imagine it's something like this...

如果是这样,我想它是这样的......

MyChildClass::~MyChildClass() // virtual in header
{
    // Call to base destructor...
    this->MyBaseClass::~MyBaseClass();

    // Some destructing specific to MyChildClass
}

Am I right?

我对吗?

回答by Lou Franco

No, destructors are called automatically in the reverse order of construction. (Base classes last). Do not call base class destructors.

不,析构函数以与构造相反的顺序自动调用。(基类最后)。不要调用基类析构函数。

回答by Brian R. Bondy

No you don't need to call the base destructor, a base destructor is always called for you by the derived destructor. Please see my related answer here for order of destruction.

不,您不需要调用基析构函数,派生析构函数总是为您调用基析构函数。 请在此处查看我的相关答案以了解销毁顺序

To understand why you want a virtual destructor in the base class, please see the code below:

要了解为什么要在基类中使用虚拟析构函数,请参阅以下代码:

class B
{
public:
    virtual ~B()
    {
        cout<<"B destructor"<<endl;
    }
};


class D : public B
{
public:
    virtual ~D()
    {
        cout<<"D destructor"<<endl;
    }
};

When you do:

当你这样做时:

B *pD = new D();
delete pD;

Then if you did not have a virtual destructor in B, only ~B() would be called. But since you have a virtual destructor, first ~D() will be called, then ~B().

然后,如果您在 B 中没有虚拟析构函数,则只会调用 ~B() 。但是因为你有一个虚拟析构函数,首先 ~D() 将被调用,然后 ~B() 将被调用。

回答by Brian R. Bondy

What the others said, but also note that you do not have to declare the destructor virtual in the derived class. Once you declare a destructor virtual, as you do in the base class, all derived destructors will be virtual whether you declare them so or not. In other words:

其他人说什么,还要注意您不必在派生类中声明析构函数 virtual 。一旦你声明了一个虚拟的析构函数,就像你在基类中所做的那样,无论你是否声明它们,所有派生的析构函数都将是虚拟的。换句话说:

struct A {
   virtual ~A() {}
};

struct B : public A {
   virtual ~B() {}   // this is virtual
};

struct C : public A {
   ~C() {}          // this is virtual too
};

回答by itsmatt

No. Unlike other virtual methods, where you would explicitly call the Base method from the Derived to 'chain' the call, the compiler generates code to call the destructors in the reverse order in which their constructors were called.

不。与其他虚方法不同,在其他虚方法中,您将从 Derived 显式调用 Base 方法以“链接”调用,编译器生成代码以调用析构函数的顺序与调用析构函数的顺序相反。

回答by zar

No, you never call the base class destructor, it is always called automatically like others have pointed out but here is proof of concept with results:

不,你永远不会调用基类析构函数,它总是像其他人指出的那样自动调用,但这里是带有结果的概念证明:

class base {
public:
    base()  { cout << __FUNCTION__ << endl; }
    ~base() { cout << __FUNCTION__ << endl; }
};

class derived : public base {
public:
    derived() { cout << __FUNCTION__ << endl; }
    ~derived() { cout << __FUNCTION__ << endl; } // adding call to base::~base() here results in double call to base destructor
};


int main()
{
    cout << "case 1, declared as local variable on stack" << endl << endl;
    {
        derived d1;
    }

    cout << endl << endl;

    cout << "case 2, created using new, assigned to derive class" << endl << endl;
    derived * d2 = new derived;
    delete d2;

    cout << endl << endl;

    cout << "case 3, created with new, assigned to base class" << endl << endl;
    base * d3 = new derived;
    delete d3;

    cout << endl;

    return 0;
}

The output is:

输出是:

case 1, declared as local variable on stack

base::base
derived::derived
derived::~derived
base::~base


case 2, created using new, assigned to derive class

base::base
derived::derived
derived::~derived
base::~base


case 3, created with new, assigned to base class

base::base
derived::derived
base::~base

Press any key to continue . . .

If you set the base class destructor as virtual which one should, then case 3 results would be same as case 1 & 2.

如果您将基类析构函数设置为虚拟的,那么情况 3 的结果将与情况 1 和 2 相同。

回答by Beno?t

No. It's automatically called.

不,它是自动调用的。

回答by Adarsh Kumar

Destructors in C++ automatically gets calledin the order of their constructions (Derived then Base) only when the Base class destructor is declared virtual.

只有在声明了 Base 类析构函数时,C++ 中的析构函数才会按照它们的构造顺序(Derived 然后 Base)自动被调用virtual

If not, then only the base class destructor is invoked at the time of object deletion.

如果不是,则在对象删除时仅调用基类析构函数。

Example: Without virtual Destructor

示例:没有虚拟析构函数

#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}

Output

输出

Base Constructor
Derived Constructor
Base Destructor

Example: With Base virtual Destructor

示例:使用 Base 虚拟析构函数

#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  //virtual destructor
  virtual ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
    delete(n);  //deleting the memory used by pointer
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}

Output

输出

Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

It is recommended to declare base class destructor as virtualotherwise, it causes undefined behavior.

建议声明基类析构函数,virtual否则会导致未定义的行为。

Reference: Virtual Destructor

参考:虚拟析构函数