5

クラス A のコンストラクターからスローされた次の例外が 2 回キャッチされるのはなぜですか? 1 回目はコンストラクター自体のキャッチで、2 回目はメイン関数のキャッチでキャッチされます。

コンストラクター内の catch で一度だけキャッチされないのはなぜですか?

 #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 ブロックを削除すると、プログラムがクラッシュします。出力は次のとおりです。

Exception thrown in A()
terminate called after throwing an instance of 'E'
zsh: abort (core dumped)  ./main

メイン関数に try-catch ブロックがないとクラッシュするのはなぜですか?

4

3 に答える 3

3

コンストラクター内の関数試行ブロックは例外を防ぐことができません。コンストラクターで例外が発生すると、 object がなくなり、例外が伝播する必要があります。function-try-block が実行できる唯一のことは、ローカル クリーンアップです。

コンストラクターは、関数の試行ブロックに関して非常に特別な動物です。

参照。C++11 15.3/14:

コンストラクタまたはデストラクタのfunction-try-blockのハンドラの最後に制御が到達すると、現在処理されている例外が再スローされます。


Tl;dr: function-try-blocks は絶対に使用しないでください。

于 2013-10-30T15:48:53.883 に答える
2

論理的に思えます。次の 2 つのシナリオを検討してください。

私。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
  }

ii. Try ブロックはイニシャライザ ctor にあります:

  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!
  }

最初のケースでは、例外の後、コンストラクター内でそれを処理し、オブジェクトを適切に構築します。

2 番目のケースでは、例外の後、そこで処理します。しかし、まだオブジェクトを構築しておらず、呼び出し側にオブジェクトがありません。呼び出し元は、構築されていないオブジェクトの状況を処理する必要があります。

于 2013-10-30T15:51:38.700 に答える
2

function-try-catchという機能を利用しています。コンストラクターで使用すると、コンストラクター本体だけでなく、初期化リスト (基本クラスのコンストラクターで例外をキャッチする場合に特に便利) で例外をキャッチできます。ただし、例外はコンストラクターでスローされるため、クラスは不完全であるため、コンパイラーはキャッチされた例外を自動的に再スローします。そのため、2 回キャッチされます。

詳細については、次の記事を参照してください。

C++ のコンストラクターと例外

于 2013-10-30T15:59:24.473 に答える