C++ 例外処理

例外とは、プログラムの実行中に発生する問題です。C++ の例外とは、プログラムの実行時に発生する特別な状況、例えばゼロ除算の試みなどを指します。

例外は、プログラムの制御を移す方法を提供します。C++ の例外処理には3つのキーワードが関わります:try、catch、throw。

  • throw:問題が発生すると、プログラムは例外をスローします。これは次のものを使用して行われます。throwキーワードによって行われます。
  • catch:問題を処理したい場所で、例外ハンドラによって例外をキャッチします。catchキーワードは例外をキャッチするために使用されます。
  • try: tryブロック内のコードは、アクティブになる特定の例外を識別します。その後に通常1つ以上の catch ブロックが続きます。

ブロックが例外をスローする場合、例外をキャッチする方法ではtryとcatchcatch キーワードを使用します。try ブロックには例外をスローする可能性のあるコードを配置し、try ブロック内のコードは保護コードと呼ばれます。try/catch 文の構文は次のとおりです:

try { // 保護コード }catch( ExceptionName e1 ) { // catch ブロック }catch( ExceptionName e2 ) { // catch ブロック }catch( ExceptionName eN ) { // catch ブロック }

もしtryブロックが異なる状況で異なる例外をスローする場合、このとき複数のcatchcatch 文を列挙して、異なるタイプの例外をキャッチすることができます。

例外をスローする

あなたは次を使用できます:throwthrow 文。コードブロック内の任意の場所で例外をスローできます。throw 文のオペランドは任意の式であり、式の結果の型がスローされる例外の型を決定します。

以下は、ゼロ除算を試みたときに例外をスローする例です:

double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); }

例外をキャッチする

catchcatch ブロックはtrytry ブロックの後に続き、例外をキャッチするために使用されます。キャッチしたい例外の型を指定できます。これは、catch キーワードの後の括弧内の例外宣言によって決定されます。

try { // 保護コード }catch( ExceptionName e ) { // ExceptionName 例外を処理するコード }

上記のコードは、型が次のものである例外をキャッチします。ExceptionNameの例外をキャッチします。catch ブロックに try ブロックがスローするあらゆる型の例外を処理させたい場合は、例外宣言の括弧内に省略記号 ... を使用する必要があります。次のようになります:

try { // 保護コード }catch(...) { // あらゆる例外を処理できるコード }

以下は、ゼロ除算の例外をスローし、catch ブロックでその例外をキャッチする例です。

例

#include <iostream> using namespace std; double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); } int main () { int x = 50; int y = 0; double z = 0; try { z = division(x, y); cout << z << endl; }catch (const char* msg) { cerr << msg << endl; } return 0; }

私たちは型が次のものである例外をスローしたため、const char*の例外をスローしたため、その例外をキャッチするときは、catch ブロックで const char* を使用する必要があります。上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

Division by zero condition!

C++ 標準の例外

C++ は一連の標準例外を提供しており、それらは次に定義されています。<exception>の中に定義されています。プログラム内でこれらの標準例外を使用できます。それらは親子クラスの階層構造で編成されており、次のようになります:

C++ 异常的层次结构

次の表は、上記の階層構造に登場する各例外の説明です:

例外 説明
std::exception この例外は、すべての標準 C++ 例外の親クラスです。
std::bad_alloc この例外はnewによってスローされます。
std::bad_cast この例外はdynamic_castによってスローされます。
std::bad_typeid この例外はtypeidによってスローされます。
std::bad_exception これは、C++ プログラムで予期しない例外を処理するときに非常に役立ちます。
std::logic_error 理論的にはコードを読むことで検出できる例外です。
std::domain_error 無効な数学ドメインを使用したときに、この例外がスローされます。
std::invalid_argument 無効な引数を使用したときに、この例外がスローされます。
std::length_error 長すぎる std::string を作成したときに、この例外がスローされます。
std::out_of_range この例外は、std::vector や std::bitset<>::operator[]() などのメソッドによってスローされます。
std::runtime_error 理論的にはコードを読むことで検出できない例外です。
std::overflow_error 数学的なオーバーフローが発生したときに、この例外がスローされます。
std::range_error 範囲外の値を格納しようとしたときに、この例外がスローされます。
std::underflow_error 数学的なアンダーフローが発生したときに、この例外がスローされます。

新しい例外の定義

あなたは、exceptionクラスを継承およびオーバーロードすることで、新しい例外を定義できます。次の例は、std::exception クラスを使用して独自の例外を実装する方法を示しています:

例

#include <iostream> #include <exception> using namespace std; struct MyException : public exception { const char * what () const throw () { return "C++ Exception"; } }; int main() { try { throw MyException(); } catch(MyException& e) { std::cout << "MyException caught" << std::endl; std::cout << e.what() << std::endl; } catch(std::exception& e) { // その他のエラー } }

これにより、次の結果が生成されます:

MyException caught
C++ Exception

ここで、what()は例外クラスが提供するパブリックメソッドであり、すべてのサブ例外クラスによってオーバーロードされています。これは例外が発生した原因を返します。

その他の拡張