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

Day*_*mer 13 c++ exception virtual-destructor

当我们离开catch块范围时,是否会调用异常析构函数?(如果我们不重新抛出它)

假设我有A类,并且它的析构函数不是虚拟的.B继承A.假设某个函数将B类的对象作为异常抛出,并且它被catch块捕获

catch(A& a){
...
}
Run Code Online (Sandbox Code Playgroud)

如果在超出catch范围时应该调用异常析构函数,在这种情况下,只会调用基类A的析构函数?

Cornstalks:实时试验导致调用两个类析构函数.

这与我的逻辑相矛盾.解释某人?

Lig*_*ica 5

当我们离开catch块范围时,是否会调用异常析构函数?(如果我们不重新抛出它)

是:

[C++11: 15.1/4]: [..]异常对象在异常的最后剩余活动处理程序以除了重新抛出之外的任何方式退出之后被销毁,或者std::exception_ptr引用异常对象的类型(18.8.5)的最后一个对象被销毁,以较晚者为准.[..]


如果在超出catch范围时应该调用异常析构函数,在这种情况下只会调用基类A的de tor?

:

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


Bri*_*ian 5

好的,有人已经回答了你的第一个问题.我将专注于这一个:

如果在超出catch范围时应该调用异常析构函数,在这种情况下只会调用基类A的de tor?

无论如何捕获,实现都将始终正确地销毁异常对象.该实现构造了异常对象,因此它知道如何销毁它.这与delete通过指针调用时不同,因为在这种情况下,new除非存在虚拟析构函数,否则此时对象的完整类型(可能已在其他位置编辑)的信息不完整.

如果不是这样的话,catch (...)根本就不会有用.

  • 而且,为了完整性,当基类型没有虚拟析构函数时,通过指向基类型的指针删除指向派生对象的指针,会产生**未定义的行为**.它可能运行基础析构函数,但它可能会做一些完全不同的事情. (3认同)