Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用函数try块的构造函数会引发两次异常_C++_Exception_Exception Handling_Constructor_Try Catch - Fatal编程技术网

C++ 使用函数try块的构造函数会引发两次异常

C++ 使用函数try块的构造函数会引发两次异常,c++,exception,exception-handling,constructor,try-catch,C++,Exception,Exception Handling,Constructor,Try Catch,为什么从类A的构造函数抛出的以下异常会被捕获两次,第一次是由构造函数本身中的捕获,第二次是由主函数中的捕获 为什么它不被构造函数中的捕获捕获一次呢 #include <iostream> using namespace std; class E { public: const char* error; E(const char* arg) : error(arg) { } }; class A

为什么从类A的构造函数抛出的以下异常会被捕获两次,第一次是由构造函数本身中的捕获,第二次是由主函数中的捕获

为什么它不被构造函数中的捕获捕获一次呢

 #include <iostream>
    using namespace std;

    class E {
       public:
          const char* error;
          E(const char* arg) : error(arg) { }
    };

    class A {
       public:
          int i;

          A() try : i(0) {
             throw E("Exception thrown in A()");
          }
          catch (E& e) {
             cout << e.error << endl;
          }
    };

    int main() {

       try {
          A x;
       }
       catch(...) 
       {
        cout << "Exception caught" << endl; 
       }
    }

为什么它在主函数中没有try-catch块的情况下崩溃?

构造函数中的函数try块无法防止异常。一旦构造函数中发生异常,就没有对象,异常必须传播。函数try块只能做一些局部清理

对于函数try块,构造函数确实是一种非常特殊的动物

参见C++11 15.3/14:

如果控件到达构造函数或析构函数的函数try块的处理程序末尾,则当前处理的异常将被重试



Tl;dr:永远不要使用函数try块。

这似乎合乎逻辑。考虑以下两种情况:

一,。Try块位于构造函数的主体内:

  A() : i(0) {
    try
    {
       throw E("Exception thrown in A()");
    }
    catch (E& e) {
       cout << e.error << endl;
    }
    // If code reaches here,
    // it means the construction finished well
  }
A():i(0){
尝试
{
抛出E(“在A()中抛出异常”);
}
捕获(E&E){

cout您正在使用一个名为的功能。当在构造函数中使用时,它允许捕获初始化列表中的异常(特别适用于捕获基类构造函数中的异常)但是由于异常是在构造函数中抛出的,因此类是不完整的,因此编译器会自动重新引用捕获到的任何异常。 这就是为什么你看到它被抓了两次

有关更多详细信息,请阅读以下文章:


另外,如果将
try
放在构造函数的主体中,您将捕获一个异常。@MM.是的,这是为什么?如果没有主函数中的try-catch块,它将不再崩溃。请不要捕获省略号…正确操作并捕获相应的异常。您最好使用
const
引用捕获异常。因为您通常不想在抛出/捕获后更改它们,如果您需要创建一个新副本并重新生成此副本。那么这是否意味着虽然已执行捕获块,但它捕获但随后失败?但为什么在构造函数中使用try-catch捕获一次?函数try-blocks和try-catc之间有什么区别函数中的h块?@takwing:是的。初始化过程中引发的异常意味着对象无法正确构造,因此不应该存在。如果在外部捕捉到异常,则可以处理对象构造失败的事实。如果在构造函数主体内捕捉到异常,则它将不会是异常这源于初始化,但源于成功构造后执行的某个语句。@takwing:作用域不同。函数体作用域内有一个普通的try/catch块。函数体作用域周围有一个函数try块。@KerrekSB:顺便问一句,如果有的话,什么是真正的有趣用例tion try block?@M,调用方捕获的第二个异常是否与构造函数抛出的第一个异常不同?根据您的解释,第二个异常应该是异常,因为对象的构造不完整,对吗?@takwing:不,它们是相同的。是的。事实上,第二个场景将是在异常中划行。
  A() : i(0) {
    try
    {
       throw E("Exception thrown in A()");
    }
    catch (E& e) {
       cout << e.error << endl;
    }
    // If code reaches here,
    // it means the construction finished well
  }
  A() try : i(0) {
     throw E("Exception thrown in A()");
  }
  catch (E& e) {
     cout << e.error << endl;

     // OK, you handled the exception,
     // but wait you didn't construct the object!
  }