简体   繁体   English

非虚析构函数c ++的异常

[英]exception with non virtual destructor c++

When we go out of catch block scope, does the exception destructor get called? 当我们离开catch块范围时,是否会调用异常析构函数? (In case we don't rethrow it) (如果我们不重新抛出它)

Suppose I have class A, and that its destructor is not virtual. 假设我有A类,并且它的析构函数不是虚拟的。 B inherits A. Suppose some function threw object of B class as an exception, and it was caught by a catch block B继承A.假设某个函数将B类的对象作为异常抛出,并且它被catch块捕获

catch(A& a){
...
}

If the exception destructor should be called when go out of catch scope, in this case only the base class A's destructor will be called? 如果在超出catch范围时应该调用异常析构函数,在这种情况下,只会调用基类A的析构函数?

Cornstalks: live trial result in calling both class destructor. Cornstalks:实时试验导致调用两个类析构函数。

It contradicts my logic. 这与我的逻辑相矛盾。 Explain someone? 解释某人?

when we go out of catch block scope, does the exception destructor is called? 当我们离开catch块范围时,是否会调用异常析构函数? (In case we don't rethrow it) (如果我们不重新抛出它)

Yes: 是:

[C++11: 15.1/4]: [..] The exception object is destroyed after either the last remaining active handler for the exception exits by any means other than rethrowing, or the last object of type std::exception_ptr (18.8.5) that refers to the exception object is destroyed, whichever is later. [C++11: 15.1/4]: [..]异常对象在异常的最后剩余活动处理程序以除了重新抛出之外的任何方式退出之后被破坏,或者是std::exception_ptr类型的最后一个对象(18.8) .5)引用异常对象被销毁,以较晚者为准。 [..] [..]


if the exception destructor should be called when go out of catch scope, in this case only the base class A's d'tor will be called? 如果在超出catch范围时应该调用异常析构函数,在这种情况下只会调用基类A的de tor?

No :

#include <iostream>

struct A
{
    A() { std::cout << "A()"; }
    A(const A&) { std::cout << "A(const A&)"; }
    A(A&&) { std::cout << "A(A&&)"; }
    ~A() { std::cout << "~A()"; }
};

struct B : A
{
    B() { std::cout << "B()"; }
    B(const B&) { std::cout << "B(const B&)"; }
    B(B&&) { std::cout << "B(B&&)"; }
    ~B() { std::cout << "~B()"; }
};

int main()
{
    try {
        throw B();
    }
    catch (A&) {
    }
}

// Output: A()B()~B()~A()

OK, someone already answered your first question. 好的,有人已经回答了你的第一个问题。 I'll focus on this one: 我将专注于这一个:

if the exception destructor should be called when go out of catch scope, in this case only the base class A's d'tor will be called? 如果在超出catch范围时应该调用异常析构函数,在这种情况下只会调用基类A的de tor?

The implementation will always destroy the exception object properly regardless of how it is caught. 无论如何捕获,实现都将始终正确地销毁异常对象。 The implementation constructs the exception object, so it knows how to destroy it. 该实现构造了异常对象,因此它知道如何销毁它。 This is not the same as when you call delete through a pointer, because in that case there is incomplete information about the complete type of the object at that point (it may have been new ed somewhere else) unless a virtual destructor exists. 这与通过指针调用delete时不同,因为在这种情况下,除非存在虚拟析构函数,否则此时对象的完整类型(可能是其他地方的new编辑)的信息不完整。

Were this not the case, catch (...) would never work at all. 如果不是这样的话, catch (...)将永远不会起作用。

While I'm not quoting from the standard, it seems that throwing a B and catching a A& will result in both A 's and B 's destructors getting called. 虽然我没有引用标准,但似乎抛出一个B并且捕获A&将导致AB的析构函数被调用。 Live demo : 现场演示

#include <iostream>

struct A
{
    ~A() { std::cout << "A::~A" << std::endl; }
};

struct B : public A
{
    ~B() { std::cout << "B::~B" << std::endl; }
};

void throwit()
{
    throw B{};
}

int main()
{
    std::cout << "beginning main scope" << std::endl;

    {
        std::cout << "beginning inner scope" << std::endl;

        try
        {
            std::cout << "calling throwit()" << std::endl;
            throwit();
        }
        catch (A& a)
        {
            std::cout << "caught exception" << std::endl;
        }

        std::cout << "ending inner scope" << std::endl;
    }

    std::cout << "ending main scope" << std::endl;
}

Output: 输出:

beginning main scope 开始主要范围
beginning inner scope 开始内在范围
calling throwit() 调用throwit()
caught exception 抓住了例外
B::~B B ::一B
A::~A A ::〜阿
ending inner scope 结束内部范围
ending main scope 结束主要范围

As you can see, both destructors get called. 如您所见,两个析构函数都被调用。 The extra scope printing shows very clearly exactly when the destructors get called (at the end of the catch block). 额外的范围打印非常清楚地显示了调用析构函数的时间(在catch块的末尾)。

Whenever the Standard says that an object is destroyed, it means that the correct most-derived destructor is invoked. 只要标准说对象被销毁,就意味着调用了最正确的派生析构函数。

Always. 总是。

When you polymorphically delete an object without a virtual destructor, or you terminate (via delete operator or explicit destructor call) an object of incomplete type and the proper destructor is non-trivial, the Standard does not say that object is destroyed. 当您在没有虚拟析构函数的情况下多态删除对象,或者终止(通过delete运算符或显式析构函数调用)不完整类型的对象并且正确的析构函数是非平凡的时,标准不会说该对象被销毁。 It does not say that the base class destructor is invoked. 它没有说调用基类析构函数。 It says you have undefined behavior. 它说你有未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM