3

私は例外クラスを持っています:

class MyException : public std::exception
{
public:
    MyException( char* message )
        : message_( message )
    {
        if( !message_ ) throw std::invalid_argument("message param must not be null");
    }
};

そして、私のスローサイトで:

try {
    throw MyException( NULL );
}
catch( std::exception const& e ) {
    std::cout << e.what();
}

(コードはコンパイルされていないため、エラーが発生した場合はご容赦ください)

別のスローのために構築中にコンストラクターからスローするとどうなるのだろうかと思っています。これは合法であり、catch は をキャッチすることstd::invalid_argumentになり、前にスローされた例外 ( MyException) は無視されるか取り消されると思います。

この設計の目標は、例外クラスに不変条件を適用することです。message_決して NULL であってはならず、オーバーロードで null かどうかを if 条件でチェックしたくないwhat()ので、コンストラクターでそれらをチェックし、無効な場合はスローします。

これは正しいですか、それとも動作が異なりますか?

4

3 に答える 3

4

スローするオブジェクト (この場合は) は、スローするMyExceptionに正常に構築されている必要があります。まだ構築されていないので、まだ投げていません。

MyExceptionしたがって、これは機能し、のコンストラクター内から例外をスローします。「例外の処理中に例外をスローすると、問題が発生するstd::terminate」という問題は発生しません。

于 2012-05-03T18:07:35.980 に答える
3

15.1 例外のスロー n3376

パラグラフ 7

例外処理メカニズムが、スローされる式の評価を完了した後、例外がキャッチされる前に、例外を介して終了する関数を呼び出す場合、std::terminate が呼び出されます (15.5.1)。

これは、(この場合はスローされるオブジェクトの) コンストラクターが完了するまで、特別なことは何も起こらないことを意味します。ただし、コンストラクターが完了すると、他の予期しない例外がterminate()呼び出されます。

標準は、例を提供し続けます。

struct C
{
       C() { }
       C(const C&) { throw 0; }
};

int main()
{
  try
  {
    throw C();   // calls std::terminate()
  }
  catch(C) { }
}

ここでは、オブジェクトが最初に作成されるため、terminate が呼び出されます。しかしその後、例外を保留場所 (15.1.4) にコピーするためにコピー構築が呼び出されます。この関数呼び出し (コピー構築) 中に、キャッチされない例外が生成されるため、terminate が呼び出されます。

したがって、示されているコードは期待どおりに機能するはずです。

  • 次のいずれか: AMyExceptionは適切なメッセージで生成され、スローされます
  • または: Astd::invalid_argumentが生成されてスローされます
于 2012-05-03T18:24:37.563 に答える
0

常に真であるはずの不変条件をチェックしたい場合は、アサーションを使用する必要があります。例外は、コーナーケースや不適切なユーザー入力など、発生が予想される異常な状況を対象としています。

例外を使用してコードのバグを報告すると、catch(...)で誤ってバグを非表示にする可能性があります。これは、ライブラリコードを記述している場合に特に重要です。これは、システムが無効な状態になったことを意味する場合でも、他の人が例外をキャッチして無視する可能性があるかどうかがわからないためです。

アサーションのもう1つの利点は、必要に応じてアサーションを完全に無効にできることです。これにより、パフォーマンスの低下が発生しなくなります。これにより、デバッグビルドでこれらのチェックを非常に気にせずに、非常に高速なリリースビルドを行うことができます。

于 2012-05-03T18:44:51.637 に答える