2009-05-25 14 views
2

質問1:C++では、std :: exceptionによってキャッチされない例外をスローすることは可能ですか?

ですがのstd ::例外でキャッチされることはありません例外をスローすることは可能でしょうか?

try 
{ 
} 
catch(std::exception & e) 
{ 
} 
catch(...) 
{ 
    //Is this block needed? 
} 

質問2:

はそれを持っている方が良いです:

catch(std::exception & e) 

それとも

catch(std::exception e) 

それとも

catch(const std::exception &e)//<--- this is the method I usually use 

答えて

11

Q1:はい。任意の型をスローすることができますが、std :: exceptionから継承する必要はありません。
throw 1;をスローするにはintを、throw "hello";にはchar*を投げてください。いずれもstd::exceptionを継承しません。しかし、これは悪い習慣とみなされます。なぜなら、クラスのユーザーはあなたが何かを投げることを期待できないからです。 std::exceptionから継承したくない場合は、独自の例外階層を作成します。

Q2:値(2番目のオプション)で例外をキャッチすることは、例外インスタンスを強制的にコピーし、さらに例外を発生させる可能性のある割り当てを強制するため、悪い習慣です。
最初のオプションを使用すると、catchブロック内のeを変更する予定があります。これは、通常、作成後に例外が不変に維持されるため避けたいものです。残っているのは第3の選択肢だけです。

+0

"残っているのは第3のオプションです" - 本当に良いオプションではない別のオプションは、ポインタでスローしてキャッチすることです。 – ChrisW

+0

@ChrisW:マイクロソフトがCOMを通じて一般的なオプションを作ったとしても、一般的にはポインタを投げてキャッチすることはお勧めしません。 http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.6 –

+3

@dribeas - COMは例外を全く異なる方法で実行します。しかし、MSはポインタを投げたりキャッチしたりするためにMFCライブラリを設計しました。これは、最初に実装しようとしたときに、C++コンパイラが例外をサポートしなかったためです。だから、setjmp/longjmpにはマクロがあり、スタックを巻き戻すことはありません...すごくハーフベークしました。 –

6

確かに、任意のタイプをスローすることができ、それはstd::exceptionから派生する必要はありません。

constを参照してください。その理由は、constまたは非constを投げることができ、constで捕らえることができるからです。 constの静かなキャスティングのような作品です。

+1

たとえば、「throw 1;」合法です。 – ChrisW

+0

私は 'スロー'が大好きです。テストコードのために "Fnugle not found"が見つかりました。 – peterchen

+0

constをキャッチする方が良い理由の例を教えてください。代わりにstd :: exception eを捕まえる危険な状況ですか? –

4

2番目の質問に対する答えは、価値のあるものを投じて参照することです。あなたが価値をつかむなら、あなたは 'object slicing'を得るかもしれません。

+1

コピー中に他の例外を引き起こす可能性があるという不便さ(例外内部データのコピー、内部バッファの割り当て - メッセージ文字列を含む) –

0

std :: exceptionを継承しない例外をスローする必要があることがあります。共有ライブラリを出荷するときは、すべての種類のリンカー/コンパイラの相互運用性の問題を引き起こす可能性があるため、それらを直接使用するメソッド/関数を公開するのではなく、ほとんどのstdライブラリ型を再実装するかラップするのがベストプラクティスです。

関連する問題