6

デスクトップアプリケーションプロジェクトにQT4.8(C ++)を使用しており、次のような例外処理を記述しています。

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;
  }
}

だから私の質問は、すべてのキャッチブロックにクリーンアップコードを書く必要がありますか?繰り返されるコードを書かないようにする方法はありますか?

::[ method1()で]呼び出し元に発生した例外を再スローしたいので、タイプ情報が失われるため、単一のcatchブロックでそれらをキャッチできません。

4

3 に答える 3

8

Method1は、次の2つの概念によって大幅に簡略化できます。

  1. RAIIクリーンアップコードをデストラクタに入れると、クリーンアップコードが一元化されます。
  2. 修飾されていないを使用するthrowと、スローされた例外のタイプについて知る必要がなくなります。

したがって、次のmethod1()ようになります。

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

メソッドは仮想であるため、からException1を派生させる場合は、の最初のcatch句をcallerMethod削除できます。std::exceptionwhat()

于 2012-04-21T06:44:43.797 に答える
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";
}

これは、より適切に処理する予定のない例外をスローしたり、失敗した操作などを再試行したりする場合にのみ可能です。

このアプローチの長所は、すべて/ほとんどのエラー処理コードがプログラムのトップレベルにあり、呼び出しチェーン内のすべての関数がこのことについて少し心配する必要がないことです。例外をスローするだけです。彼らがそれのように感じるとき。

于 2012-04-21T07:25:55.540 に答える
0

すべてのクリーンアップコードが完全に同一である場合、catch(...)ブロックですべてを実行できます。

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;
}
于 2012-04-21T06:44:51.073 に答える