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

Nic*_*ton 327 c++ destructor

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

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

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

    // Some destructing specific to MyChildClass
}
Run Code Online (Sandbox Code Playgroud)

我对吗?

Lou*_*nco 442

不,析构函数会按照相反的构造顺序自动调用.(基础课最后).不要调用基类析构函数.

  • 你没有一个没有身体的纯虚拟析构函数.只要给它一个空体.使用常规纯虚方法,调用覆盖函数,使用析构函数,它们都被调用,因此您必须提供一个正文.= 0只意味着它必须被覆盖,所以如果你需要它仍然是一个有用的构造. (39认同)
  • 任何错误的代码都不能保证您的分段错误.此外,调用析构函数不会释放内存. (2认同)

Bri*_*ndy 90

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

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

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


class D : public B
{
public:
    virtual ~D()
    {
        cout<<"D destructor"<<endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

当你这样做时:

B *pD = new D();
delete pD;
Run Code Online (Sandbox Code Playgroud)

然后,如果B中没有虚拟析构函数,则只调用~B().但是因为你有一个虚拟的析构函数,所以先调用~D()然后调用~B().

  • 请包括程序(伪)输出.它会帮助读者. (20认同)

小智 26

其他人说了什么,但也注意到你不必在派生类中声明析构函数virtual.一旦声明了析构函数virtual,就像在基类中那样,所有派生的析构函数都是虚拟的,无论你是否声明它们.换一种说法:

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

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

struct C : public A {
   ~C() {}          // this is virtual too
};
Run Code Online (Sandbox Code Playgroud)

  • 是.当虚拟方法(任何,而不仅仅是析构函数)被声明为虚拟时,派生类中该方法的所有覆盖都将自动为虚拟.在这种情况下,即使你没有声明〜B虚拟,它仍然是,所以是~C. (5认同)
  • @YuanWen 不,它不会,(唯一的)派生析构函数总是覆盖其基类的(唯一的)析构函数。 (2认同)

its*_*att 10

否.与其他虚拟方法不同,您将显式调用Derived中的Base方法来"调用"链接,编译器会生成代码,以按照调用构造函数的相反顺序调用析构函数.


zar*_*zar 8

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

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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

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 . . .
Run Code Online (Sandbox Code Playgroud)

如果将基类析构函数设置为虚拟的,那么案例3的结果将与案例1和2相同.


小智 8

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

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

示例:没有虚拟析构函数

#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;

}
Run Code Online (Sandbox Code Playgroud)

输出

Base Constructor
Derived Constructor
Base Destructor
Run Code Online (Sandbox Code Playgroud)

示例:使用 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;

}
Run Code Online (Sandbox Code Playgroud)

输出

Base Constructor
Derived Constructor
Derived Destructor
Base Destructor
Run Code Online (Sandbox Code Playgroud)

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

参考:虚拟析构函数


Ben*_*oît 6

不,它是自动调用的.