C ++-捕获双重异常

时间:2018-06-20 10:15:35

标签: c++ exception exception-handling destructor constructor-exception

我有以下代码:

#include <iostream>
using namespace std;

class A {
public:
    A()  { cout << "A::A()" << endl;}
    ~A() { cout << "A::~A()" << endl; throw "A::exception";}
};

class B {
public:
    B()  { cout << "B::B()" << endl; throw "B::exception";}
    ~B() { cout << "B::~B()";}
};

int main() {
    try {
        cout << "Entering try...catch block" << endl;
        A   objectA;
        B   objectB;
        cout << "Exiting try...catch block" << endl;
    } catch (char const * ex) {
        cout << ex << endl;
    }
    return 0;
}

现在,在说明问题之前,我想指出这段代码是不好的做法(例如,从构造函数中抛出异常将导致对象无法完全创建,因此不会调用析构函数,这可能会导致内存泄漏或其他问题。

现在,主要商品的顺序是:

  1. 打印"Entering try...catch block"

  2. 调用A的构造函数,打印"A::A()"

  3. 调用B的构造函数,打印"B::B()",并引发异常。

  4. 引发了异常,"Exiting try...catch block"将不会被打印。该块已退出,因此调用A的析构函数。

  5. A的析构函数打印"A::~A()"并引发另一个异常。

第二个异常(在5中)导致主程序在进入catch块之前引发异常。

我的问题是-是否有一种方法可以在不更改类AB的情况下捕获主变量中的第二个异常?

我试图用另一个try-catch块将整个catch块和try-catch块内包围,但这没用。

谢谢。

1 个答案:

答案 0 :(得分:5)

来自cppreference.com

  

与其他任何函数一样,析构函数可以通过引发异常来终止[...],但是,如果在堆栈展开期间恰好调用了该析构函数,则会调用std::terminate

因此,尝试从~A()引发异常不会导致引发第二个异常。导致程序终止。如果您需要“捕获”此“第二个异常”,则需要干扰the termination handler。或者,您可以找到一种在析构函数中不引发异常的方法。从cppreference.com继续:

  

尽管std::uncaught_exception有时有时可以用来检测正在进行的堆栈展开,但通常认为,允许任何析构函数通过引发异常终止的做法都是错误的做法。