2009-06-11 14 views
2

私たちは例外クラスの階層を持っています - GenericExceptionクラスとそこから派生したいくつかのクラスがあります。 GenericExceptionは多型です。仮想デストラクタを持っています。複数のcatchブロックまたはdynamic_castを持つブロック?

ファイルシステムオブジェクトを操作するときにエラーを示すために派生クラスの1つがFileExceptionにスローされます。 FileExceptionにはGetErrorCode()というコードが返され、実際に何が問題になったのかを示すコードが返されます。

階層は既に存在していますが、私はそれを変更することはできませんので、問題はありません。

例外は私たちが制御しないコードから投げられ、常に新しいというキーワードでスローされますので、ポインタでそれらを捕捉することができます。これはどちらでも問題ありません。

今や、文のセットがGenericExceptionから派生することが保証されている例外を生成する可能性がある状況があります。 FileExceptionの場合、エラー状況のタイプは「ファイルが見つかりません」です。何もしません。そうでなければ、エラーメッセージを表示したいと思います。

私は2つの選択肢がある - のいずれか:それはコードの重複を減らすので、私は最初のものを好む

} catch(FileException* e) { 
    if(fileException->GetErrorCode() != FileNotFound) { 
     ShowMessage(e); 
    } 
    delete e; 
} catch(GenericException* e) { 
    ShowMessage(e); 
    delete e; 
} 

} catch(GenericException* e) { 
    FileException* fileException = dynamic_cast<FileException*>(e); 
    if(fileException == 0 || fileException->GetErrorCode() != FileNotFound) { 
     ShowMessage(e); 
    } 
    delete e; 
} 

またはこのいずれかを。しかし、私はC++が選択的キャッチブロック(2番目のオプションのような)を許可しているので、私はdynamic_castを使用してはいけないという意見を聞いたことがある - 選択的キャッチブロックはそれを必要としない。

どちらのオプションが優れていますか?ここで最初のオプションがない理由は何でしょうか?

+0

少なくとも、新しい例外が実行できなかった場合に備えて、どこでもcatch(bad_alloc&)ブロックが必要です。 – Pieter

+0

そして、彼はそのようなブロックで何をしますか? –

答えて

4

決してポインタを投げるべきではありません。常に値をスローし、const 参照をキャッチします。動的に割り当てられた例外オブジェクトを正しくクリアすることは決して不可能です。

あなたの質問に答えるために、私は個人的に複雑な例外階層を持つことを信じていません。例外に対して条件付き処理を実行する必要がある場合は、現在行っているように見えるよりもコンテキスト情報が多いスローサイトに近い例外を処理する必要があります。

+0

2つの段落のどちらも質問に答えません...投げ縄のコードは私のコントロール外です。 – sharptooth

+0

"ダイナミックに割り当てられた例外オブジェクトを正しくクリアすることは決してできません" - なぜですか?あなたがそれを捕まえれば、確かにそれを割り当て解除することができます。あなたがそれをキャッチしなければ、はい、しかし、キャッチされていない例外はおそらく、プロセスを停止させるでしょう。しかし、それは間違いなく良い考えではありません。 –

2

二番目のオプションは、あなたがconstの& ;-)
でそれを書き換える場合、私は最初のものよりもはるかにきれい秒見つける「最高」で、それは明らかにあなたが欲しいものを示しています。

3

私は2番目を好むでしょう。

重複が懸念される場合は、「例外ディスパッチャ」と呼ばれるものを認識していますか?同じキャッチ処理を実行する必要のある場所がたくさんある場合は、そのキャッチ処理をすべて1つの関数に置き、catch(...)ブロックからこの関数を呼び出します。

void fn() 
{ 
    try 
    { 
     MightThrow(); 
    } 
    catch (...) 
    { 
     ExceptionHandler(); 
    } 
} 

void ExceptionHandler() 
{ 
    try 
    { 
     throw; 
    } 
    catch(FileException* e) { 
     if(fileException->GetErrorCode() != FileNotFound) { 
      ShowMessage(e); 
     } 
     delete e; 
    } catch(GenericException* e) { 
     ShowMessage(e); 
     delete e; 
    } 
} 

これは、ハンドラ内の重複を停止しませんが、あなたは別の場所で同じものをキャッチする必要がある場所には、重複を停止します。

編集:あなたはexceptionHandlerのは、例外を処理していない時にそう多くの悪が発生すると呼ばれていないことを確認する必要があります。related question

0

あなたはあなたの例外からのメッセージを表示するように仮想関数を必要としています。この関数は、ルート階層クラスのメンバーでなければなりません。

関連する問題