关于c ++:我是否需要显式调用基本虚拟析构函数?

Do I need to explicitly call the base virtual destructor?

当重写C++中的类(带有虚拟析构函数)时,我在继承类上再次将析构函数作为虚函数实现,但需要调用基析构函数吗?

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

1
2
3
4
5
6
7
MyChildClass::~MyChildClass() // virtual in header
{
    // Call to base destructor...
    this->MyBaseClass::~MyBaseClass();

    // Some destructing specific to MyChildClass
}

我说的对吗?


不,析构函数按构造的相反顺序自动调用。(上一个基类)。不要调用基类析构函数。


不,您不需要调用基析构函数,派生析构函数总是为您调用基析构函数。有关销毁顺序,请参阅我的相关答案。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class B
{
public:
    virtual ~B()
    {
        cout<<"B destructor"<<endl;
    }
};


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

当你这样做的时候:

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

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


其他人所说的,但也要注意,您不必在派生类中声明析构函数virtual。一旦声明了析构函数virtual,就像在基类中一样,所有派生析构函数都将是virtual,无论您是否声明它们。换言之:

1
2
3
4
5
6
7
8
9
10
11
struct A {
   virtual ~A() {}
};

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

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


不。与其他虚拟方法不同,在这种方法中,您将显式地从派生方法调用基方法以"链接"调用,编译器生成代码,以按照调用其构造函数的相反顺序调用析构函数。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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;
}

输出是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 . . .

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


不,它是自动呼叫的。