Catch ブロックの評価方法 (C++)

C++ では任意の型の例外をスローすることができますが、一般に std::exception から派生した型をスローすることが推奨されます。 C++ 例外は、スローされた例外と同じ型を指定する catch ハンドラー、またはすべての型の例外をキャッチできるハンドラーによってキャッチできます。

スローされる例外の型がクラスである場合、クラスは基底クラスも持つため、その例外は、例外の型の基底クラスを受け入れるハンドラー、および例外の型の基底クラスへの参照を受け入れるハンドラーでキャッチできます。 例外が参照によってキャッチされた場合、それは実際にスローされた例外オブジェクトにバインドされることに注意してください。それ以外の場合は、コピーになります (関数の引数とほぼ同じ)。

スローされた例外は、次のような種類の catch ハンドラーによってキャッチできます。

  • 任意の型を受け取ることができるハンドラー (省略記号構文を使用)。

  • 例外オブジェクトと同じ型を受け取るハンドラー。例外オブジェクトはコピーであるため、const 修飾子と volatile 修飾子は無視されます。

  • 例外オブジェクトと同じ型への参照を受け入れるハンドラー。

  • 例外オブジェクトと同じ型の const または volatile 形式への参照を受け取るハンドラー。

  • 例外オブジェクトと同じ型の基底クラスを受け入れるハンドラー。例外オブジェクトはコピーであるため、const 修飾子と volatile 修飾子は無視されます。 基底クラスの catch ハンドラーは、派生クラスの catch ハンドラーの前に指定しないでください。

  • 例外オブジェクトと同じ型の基底クラスへの参照を受け取るハンドラー。

  • 例外オブジェクトと同じ型の基底クラスの const または volatile 形式への参照を受け取るハンドラー。

  • スローされたポインター オブジェクトが標準的なポインター変換規則によって変換できるポインターを受け取るハンドラー。

特定の try ブロックのハンドラーは出現順にチェックされるため、catch ハンドラーの出現順序は重要です。 たとえば、派生クラスのハンドラーの前に基底クラスのハンドラーを配置するとエラーになります。 一致する catch ハンドラーが見つかると、後続のハンドラーはチェックされません。 そのため、省略記号の catch ハンドラーは、try ブロックの最後のハンドラーにする必要があります。 次に例を示します。

// ...
try
{
    // ...
}
catch( ... )
{
    // Handle exception here.
}
// Error: the next two handlers are never examined.
catch( const char * str )
{
    cout << "Caught exception: " << str << endl;
}
catch( CExcptClass E )
{
    // Handle CExcptClass exception here.
}

この例では、省略記号の catch ハンドラーが、チェックされる唯一のハンドラーです。

関連項目

例外とエラー処理に関する最新の C++ のベスト プラクティス