例外処理関数の使用例

C++次の例は、制御の流れと、例外処理で使用する特殊な関数を示しています。

#include <iostream>
#include <exception>
using namespace std;
 
class X { };
class Y { };
class A { };
 
// pfv type is pointer to function returning void
typedef void (*pfv)();
 
void my_terminate() {
  cout << "Call to my terminate" << endl;
  abort();
}
 
void my_unexpected() {
  cout << "Call to my_unexpected()" << endl;
  throw;
}
 
void f() throw(X,Y, bad_exception) {
  throw A();
}
 
void g() throw(X,Y) {
  throw A();
}
 
int main()
{
  pfv old_term = set_terminate(my_terminate);
  pfv old_unex = set_unexpected(my_unexpected);
  try {
    cout << "In first try block" << endl;
    f();
  }
  catch(X) {
    cout << "Caught X" << endl;
  }
  catch(Y) {
    cout << "Caught Y" << endl;
  }
  catch (bad_exception& e1) {
    cout << "Caught bad_exception" << endl;
  }
  catch (...) {
    cout << "Caught some exception" << endl;
  }
 
  cout << endl;
 
  try {
    cout << "In second try block" << endl;
    g();
  }
  catch(X) {
    cout << "Caught X" << endl;
  }
  catch(Y) {
    cout << "Caught Y" << endl;
  }
  catch (bad_exception& e2) {
    cout << "Caught bad_exception" << endl;
  }
  catch (...) {
    cout << "Caught some exception" << endl;
  }
}

次に、上記の例の出力を示します。

In first try block
Call to my_unexpected()
Caught bad_exception
 
In second try block
Call to my_unexpected()
Call to my terminate

実行時に、このプログラムは次のように振る舞います。

  1. set_terminate() を呼び出すと、set_terminate() が以前に呼び出されたときに、 最後に set_terminate() に渡された関数のアドレスが old_term に割り当てられます。
  2. set_unexpected() を呼び出すと、set_unexpected() が以前に呼び出されたときに、 最後に set_unexpected() に渡された関数のアドレスを old_unex に割り当てます。
  3. 最初の try ブロックの中で、関数 f() が呼び出されます。 f() が、予期しない例外をスローするので、unexpected() への呼び出しが行われます。 次に、unexpected() は、my_unexpected() を呼び出し、標準出力にメッセージを印刷します。 関数 my_unexpected() は、型 A の例外を再度スローしようとします。 クラス A が、関数 f() の例外指定で指定されていないので、 my_unexpected() は、型 bad_exception の例外をスローします。
  4. bad_exception が、関数 f() の例外指定で指定されているので、 ハンドラー catch (bad_exception& e1) は、例外を処理することができます。
  5. 2 番目の try ブロックの中では、関数 g() が呼び出されます。 g() が、予期しない例外をスローするので、unexpected() への呼び出しが行われます。 unexpected() は、型 bad_exception の例外をスローします。 bad_exception は、g() の例外指定に指定されていないので、unexpected() は、terminate() を呼び出し、 これが関数 my_terminate() を呼び出します。
  6. my_terminate() は、メッセージを表示してから、abort() を呼び出し、これがプログラムを終了します。

例外が、my_unexpected() によって、有効な例外としてではなく、予期しないスロー (throw) として 処理されたので、2 番目の try ブロックに続く catch ブロックには、入らないことに留意してください。

関連参照

IBM Copyright 2003