2012-04-21 11 views
5

私は、デスクトップアプリケーションのプロジェクトのためにQT 4.8(C++)を使用して、以下のようにある例外処理を書いています:catchブロックに繰り返しコードを書くことを避けるには?

void callerMethod() 
{ 
    try 
    { 
    method1(); 
    } 
    catch(Exception1& e) 
    { 
    // display critcal error message 
    // abort application 
    } 
    catch(std::Exception& e) 
    { 
    // print exception error message 
    } 
    catch(...) 
    { 
    // print unknown exception message 
    } 
} 

void method1() 
{ 
    try 
    { 
    // some initializations 
    // some operations (here exceptions can occur) 
    // clean-up code (for successful operation i.e no exception occurred) 
    } 
    catch(Exception1& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception2& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception3& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(...) 
    { 
    // clean-up code 
    throw; 
    } 
} 

だから私の質問は、私はすべてのcatchブロックでクリーンアップコードを記述する必要があります ? できることは何ですか繰り返しコードを書くことを避けますか?

NOTE :: [method1には()]私はその情報が失われるタイプので、私は、単一のcatchブロック、 でそれらをキャッチすることはできません私のcaller.Soに を発生し、再スロー例外をしたいです。

+4

oスマートポインタ、コンテナクラスなどを使用して必要とされるクリーンアップコードの量を減らす。理想的には、クリーンアップコードが全くないはずです。 – user763305

+0

あなたがしたいのは、単純に 'try {/ * throw * /} catch(specific_exception const&e){/ * terminate * /}'です。例外タイプ 'Exception1'、' Exception2'などを気にかけなければ、* catchしないでください。 –

+1

また、参照によってキャッチしても、スライスを防ぐために 'throw e;'の代わりに 'throw;'を使って再スローする必要があります。 – ereOn

答えて

8

方法1は、多くの二つの概念によって簡素化することができます。

  1. RAIIクリーンアップコードをデストラクタに入れて、クリーンアップコードを集中管理します。
  2. 未修飾のthrowを使用すると、スローされた例外の種類を知る必要はありません。

ので、method1()は次のようになります。

void method1() 
{ 
    // some initializations of RAII objects 
    // some operations (here exceptions can occur) 
} 

あなたはstd::exceptionからException1を引き出す場合what()メソッドは仮想であるため、callerMethodの最初のcatch句は、削除することができます。すべてのあなたのクリーンアップコードが全く同じであれば

+1

+1。私はそれを言いたかった。 RAIIはここの解決策です。 – Nawaz

+0

しかし、callerMethod()でException1を個別に処理したいと思います。 Exception1が発生した場合、アプリケーションを中止したいと思います。 – EngineeredBrain

+0

@アンワルシャイフ:それでもやることができます。 RAIIはクリーンアップの問題のみを解決します。 – Nawaz

0

、あなたのキャッチですべてを行うことができます(...)ブロック:あなたのコードは多少変化する場合

try { 
    // code 
} catch (...) { 
    // cleanup 
    throw; 
} 

、あなたは常にクリーンアップ関数を呼び出すことができます。

try { 
    // code 
} catch (exc1 ex) { 
    cleanup(args); 
    // exc1 specific 
    throw; 
} catch (exc2 ex) { 
    cleanup(args); 
    // exc2 specific 
    throw; 
} catch (...) { 
    cleanup(args); 
    throw; 
} 
+0

例外をスローする単一のキャッチ(..)を書くと、呼び出し元メソッドでどの例外が発生したのかを知ることができます。 アプリケーションを中止するException1を処理したいからです。 – EngineeredBrain

1

できるだけ例外をスローし、コールチェーンで可能な限り高いレベルにキャッチする必要があります。これにより、自動的にコードの重複が少なくなり、エラー処理が集中します。あなたは1つの場所ですべてを投げたりキャッチしたりしていますが、これはちょっと...強制的です。

私は、多くの場合、特に、プログラム終了の例外のためのこの種のもの(行います。

int main() 
try 
{ 
    function_calls_that_may_throw(); 
    // ... 
} 
catch(my_exception& e) 
{ 
    e.do_exception_stuff(); 
} 
catch(std::exception& e) 
{ 
    std::cout << e.what(); 
} 
catch(...) 
{ 
    std::cout << "Something bad happened.\n"; 
} 

これは、あなたが失敗した操作か何かをよりよく扱うか再試行する予定がない例外をスローするための唯一の可能性であるが

このアプローチの利点は、すべての/ほとんどのエラー処理コードがプログラムのトップレベルにあり、コールチェーン内のすべての関数がこのことについて少し気にする必要がないことです。彼らが気に入ったら例外を投げる。

関連する問題