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

当在c++中覆盖一个类(使用虚析构函数)时,我在继承类上再次实现了虚析构函数,但我需要调用基析构函数吗?

如果是这样的话,我想应该是这样的……

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


// Some destructing specific to MyChildClass
}

我说的对吗?

175236 次浏览

不,你不需要调用基析构函数,基析构函数总是由派生析构函数调用。请参阅我的相关回答在这里的破坏顺序

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

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




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

当你这样做时:

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

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

不。它会被自动调用。

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

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

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


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


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

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

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

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

输出结果为:

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 . . .

如果你将基类析构函数设置为虚函数,那么情况3的结果将与情况1相同&2.

c++ 自动被调用中的析构函数,其构造顺序(派生然后基底)仅当基类析构函数声明为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;


}

输出

Base Constructor
Derived Constructor
Base Destructor

示例:使用基本虚析构函数

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


}

输出

Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

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

参考:Virtual Destructor . bb0虚拟析构函数