【问题标题】:What is the handler of an exception raised in constructor? [duplicate]构造函数中引发的异常的处理程序是什么? [复制]
【发布时间】:2014-05-20 06:56:26
【问题描述】:

我是 C++ 异常处理的新手。我心目中的规则是,

  1. 如果在调用链(函数调用堆栈)中没有找到异常处理程序,则调用终止函数.
  2. 处理程序是一个 catch {} 块。

但是,我无法理解以下行为。

#include <iostream>
#include <exception>
using namespace std;

struct X {
  X() try { throw exception(); }
  catch (exception &e) {
    cout << "Exception caught in constructor!" << endl;
  }
};

int main() {

  try {
    throw exception();
  }
  catch (exception &e) {
    cout << "Exception caught in function." << endl;
  }
  cout << "After Exception being caught in function" << endl;

  try {
    X x;
  }
  catch (exception &e) {
    cout << "Why exception is caught again!" << endl;
  }

  return 0;
}

输出是

Exception caught in function. After Exception being caught in function Exception caught in constructor! Why exception is caught again!

问题 1: 似乎 X 的构造函数中抛出的异常被捕获(或处理)了两次。或者为什么构造函数后面的 catch{} 块不计为构造函数中异常的处理程序?

如果我不将X x; 放在try{} 块中并在main() 中捕获它,则输出为:

Exception caught in function. After Exception being caught in function Exception caught in constructor! terminate called after throwing an instance of 'std::exception' what(): std::exception Aborted (core dumped)

问题 2: 当我们在 try 块中没有 X x; 时,是否会调用默认的 terminate() 函数?

【问题讨论】:

标签: c++ c++11 exception-handling try-catch


【解决方案1】:

与:

X() try { throw exception(); }
catch (exception &e) {
    cout << "Exception caught in constructor!" << endl;
}

X 对象未完全构造,因此 catch 不能忽略异常并应重新抛出它。

IMO,当X 有一个成员抛出...(X() try : member(0) {} catch(exception&amp;) {})时更清楚。

请注意,您可以在构造函数块中使用 normal try catch:

X() {
    try { throw exception(); }
    catch (exception &e) {
        cout << "Exception caught in constructor!" << endl;
    }
}

这样更自然。

【讨论】:

  • 在我个人看来,当基类构造函数抛出时是一个更好的例子。有人可能会争辩说,您可以在成员初始化失败的情况下恢复,但不能从对象的不完整初始化中恢复。
【解决方案2】:

两个例外。

struct X {
  X() try { throw exception(); }
  catch (exception &e) {
    cout << "Exception caught in constructor!" << endl;
  }
};

发生异常后,您将在构造函数中处理它。 但是你没有构建 对象还没有,而您在调用方没有对象。呼叫者,召集者 应该处理未构造的对象情况。

第二个问题,是的。根据标准中的 [except.terminate]。它导致调用std::terminate

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
相关资源
最近更新 更多