2012-09-22 6 views
13

から例外を再スローする場合、例外タイプを失う今日はcatchブロックでバグを見つけました:私は例外e明示的を再スロー場合は、catchブロック

catch (const exception& e){ 
    // do something 
    // throw e; <-- bug! 
    throw; // <-- right thing to do 
} 

は基本的に、私は中に、再構成し、新たなstd::exceptionを取得します実際にはwhat()メソッドからのメッセージは、私のカスタム構築メッセージではなく、デフォルトのstd::stringでした。

説明は何ですか?私はthrow;throw ExceptionJustCaught;の略記だと思った。

+0

これは値と参照の違いです。 –

+0

これはしばしば見落とされる非常に重要な概念です(そして、私の意見では、少なくともコンパイル時には警告であるはずのトリッキーなビットです)。素晴らしい質問! – NHDaly

答えて

13

例外オブジェクトは少し特殊です。彼らは記憶の中の特別な場所に作られており、その生涯は捕まえられたキャッチブロックによって決まります。あなたはthrow e;言うなら

は、元の例外の寿命はcatchブロックの最後で終了し、あなたはこのように、古典的なスライス問題を生産、eをコピーして、新しい例外をスローされます:eが多型の参照があるので、ダイナミック型が通常std::exceptionよりも派生したオブジェクトに変換すると、オブジェクトの派生部分がスライスされてしまいます。これとは対照的に

throw;は、それがもはやキャッチされるように、元の例外を再活性化しない特別な声明であり、その寿命はもうブロックの終わりにない終了を行います。事実、非定数参照をキャッチした場合、例外オブジェクトを変更し続けることができます。したがって、下位キャッチブロックの状態変更を再スローして通信することができます。しかし、再スローガンは新しい例外を投げることとは異なることを覚えておいてください!

8

ただちにthrowが参照によって現在の例外をスローします。 throw e copyはスローする新しい例外を構築します。これは、returnとほぼ同じ方法です。

+0

「参考として」。正確には、これは私のメッセージを担う 'what()'の正しい実装を失ってはいけません。 –

+0

できるだけ少ない行で問題を示す完全なコンパイル可能なコード例を投稿できますか?ほとんどの場合、コピーコンストラクタはメッセージを保持しません。 –

+0

Kerrekの答えが正しいように見えますが、スライスの問題があると思われていたので、正しい答えだと思うので編集しません。おそらくデイヴィッドはちょうど異なる言葉で正しいですが、正直なところ、それは十分ではありません。 –

関連する問題