请解释析构函数调用的顺序 [英] Please explain the sequence of destructor invocations

查看:119
本文介绍了请解释析构函数调用的顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

using namespace std;

class C
{
    int a;
    public:
        C(int aa=0) {a=aa;}
        ~C() {cout << "Destructor C!" << a << endl;}
};

class D: public C
{
    int b;
    public:
        D(int aa=0, int bb=0): C(aa) {b=bb;}
        ~D() {cout << "Destructor D!" << b << endl;}
};

void test()
{
    D x(5);
    D y(6,7);
}

int main()
{
    test();
}

上面是代码,下面是运行结果:

Above is the code, and below is the running result:

Destructor D!7
Destructor C!6
Destructor D!0
Destructor C!5

我不明白为什么Destructor C!将被调用。和相关的析构函数的调用序列。我觉得它看起来像堆栈push / pop。

I don't understand why "Destructor C!" will be invoked. And the related destructor's calling sequence. I feel that it seems like the stack push/pop.

进一步:
为什么它调用 D x

Further: Why it calls "D x(5);" earlier but the corresponding result is given later?

推荐答案

析构函数调用序列总是从派生到base,就像弹出栈。这允许派生类清理你的基类分配的资源。在这种情况下,编译器知道如何构造此序列,因为它知道对象的确切类型 x y statically。

The destructor calling sequence always goes from the derived to base, like popping the stack. This allows derived classes to clean up resources allocated by your base class. In this case, the compiler knows how to construct this sequence, because it knows the exact type of the objects x and y statically.

但是,在这种情况下,这个序列会被破坏。考虑您的代码的以下修改:

There are situations, however, when this sequence would be broken. Consider the following modification of your code:

void test()
{
    C *x = new D(5);
    D *y = new D(6,7);
    delete x;
    delete y;
}

它会产生以下输出:

Destructor C!5
Destructor D!7
Destructor C!6

运行此操作不会为<$​​ c $ c> x 调用〜D y ,两个析构函数都被调用。

Running this produces no call of ~D for x; for y, both destructors are called.

这是因为你没有声明析构函数 virtual 。当析构函数不是虚拟的时,编译器不知道在一个对象被一个指向基类的指针引用的情况下,它必须调用派生类的析构函数。这就是为什么你应该总是在必须继承的类中动态创建一个虚拟的析构函数,并动态地分配资源。

This is because you did not declare the destructor virtual in the base class. When the destructor is not virtual, the compiler has no idea that it must call the destructor of the derived class in situations when an object is referred to by a pointer to a base class. This is why you should always make a destructor virtual in classes that must be inherited and allocate resources dynamically.

这篇关于请解释析构函数调用的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆