22

2つの類似したコードを想像してみてください。

try {
  [...]
} catch (myErr &err) {
  err.append("More info added to error...");
  throw err;
}

try {
  [...]
} catch (myErr &err) {
  err.append("More info added to error...");
  throw;
}

これらは事実上同じですか、それとも微妙に異なりますか?たとえば、最初のコンストラクターはコピーコンストラクターを実行しますが、2番目のコンストラクターは同じオブジェクトを再利用して再スローしますか?

4

2 に答える 2

29

例外階層の配置方法によっては、throwステートメントで例外変数に名前を付けて例外を再スローすると、元の例外オブジェクトがスライスされる場合があります。

引数なしのthrow式は、動的型を保持する現在の例外オブジェクトをスローしますが、引数付きのthrow式は、引数の静的型に基づいて新しい例外をスローしthrowます。

例えば

int main()
{
    try
    {
        try
        {
            throw Derived();
        }
        catch (Base& b)
        {
            std::cout << "Caught a reference to base\n";
            b.print(std::cout);
            throw b;
        }
    }
    catch (Base& b)
    {
        std::cout << "Caught a reference to base\n";
        b.print(std::cout);
    }

    return 0;
}

上で書いたように、プログラムは以下を出力します:

ベースへの参照をキャッチしました
派生
ベースへの参照をキャッチしました
ベース

throw bがで置き換えられた場合throw、外側のキャッチは最初にスローされたDerived例外もキャッチします。これは、内部クラスがBase参照ではなく値で例外をキャッチする場合にも当てはまります。ただし、当然、これは元の例外オブジェクトを変更できないことを意味するため、への変更は外部ブロックでキャッチさbれた例外に反映されません。Derived

于 2009-09-26T18:01:33.063 に答える
17

C++ 標準 15.1/6 による 2 番目のケースでは、コピー コンストラクターは使用されません。

オペランドのないスロー式は、処理中の例外を再スローします。例外は既存の一時的に再アクティブ化されます。新しい一時例外オブジェクトは作成されません。例外はキャッチされたとは見なされなくなります。したがって、uncaught_exception() の値は再び true になります。

最初のケースでは、15.1/3 に従って新しい例外がスローされます。

throw 式は、例外オブジェクトと呼ばれる一時オブジェクトを初期化します。その型は、throw のオペランドの静的型から最上位の cv 修飾子を削除し、「T の配列」または「」から型を調整することによって決定されます。 T を返す関数」を「T へのポインタ」または「T を返す関数へのポインタ」にそれぞれ変更します。<...> 一時は、一致するハンドラー (15.3) で指定された変数を初期化するために使用されます。throw 式の型は、void*、const void*、volatile void*、または const volatile void* 以外の不完全な型、または不完全な型へのポインターまたは参照であってはなりません。これらの制限および 15.3 で説明されている型の一致に関する制限を除き、throw のオペランドは、呼び出し (5.2.2) の関数引数または return ステートメントのオペランドとして正確に扱われます。

どちらの場合も、スロー ステージでコピー コンストラクターが必要です (15.1/5)。

スローされたオブジェクトがクラス オブジェクトであり、一時コピーの初期化に使用されるコピー コンストラクターにアクセスできない場合、プログラムの形式は正しくありません (一時オブジェクトを別の方法で削除できる場合でも)。同様に、そのオブジェクトのデストラクタにアクセスできない場合、プログラムの形式は正しくありません (一時オブジェクトを別の方法で削除できたとしても)。

于 2009-09-26T17:00:25.683 に答える