void f(int &x) try { throw 10; } catch (const int &i) { x = i; } int main() { int v = 0; f(v); }f() が呼び出された後は、v の値は、10 になります。
main() の関数 try ブロックは、静的ストレージ期間を持つオブジェクトのデストラクターで、 またはネーム・スペース・スコープ・オブジェクトのコンストラクターで、 スローされる例外をキャッチしません。
次の例は、静的オブジェクトのデストラクターから例外をスローします。この例の意図は、~B() の例外は main() の関数 try ブロックによってキャッチされるが、~A() の例外は、~A() が main() の完了後に実行されるため、キャッチされないことを示すことです。
#include <iostream> using namespace std; class E { public: const char* error; E(const char* arg) : error(arg) { } }; class A { public: ~A() { throw E("Exception in ~A()"); } }; class B { public: ~B() { throw E("Exception in ~B()"); } }; int main() try { cout << "In main" << endl; static A cow; B bull; } catch (E& e) { cout << e.error << endl; }
In main Exception in ~B()ランタイムは、オブジェクト cow が、 プログラムの終わりに破棄される時にスローされる例外をキャッチできません。
#include <iostream> using namespace std; class E { public: const char* error; E(const char* arg) : error(arg) { } }; namespace N { class C { public: C() { cout << "In C()" << endl; throw E("Exception in C()"); } }; C calf; }; int main() try { cout << "In main" << endl; } catch (E& e) { cout << e.error << endl; }上記の例の出力は、以下のとおりです。
In C()コンパイラーは、オブジェクト calf の作成時にスローされる例外をキャッチできません。
関数 try ブロックのハンドラーでは、コンストラクター本体、 またはデストラクター本体にジャンプすることはできません。
リターン・ステートメントは、コンストラクターの関数 try ブロック・ハンドラー内に置くことはできません。
#include <iostream> using namespace std; class E { public: const char* error; E(const char* arg) : error(arg) { }; }; class B { public: B() { }; ~B() { cout << "~B() called" << endl; }; }; class D : public B { public: D(); ~D() { cout << "~D() called" << endl; }; }; D::D() try : B() { throw E("Exception in D()"); } catch(E& e) { cout << "Handler of function try block of D(): " << e.error << endl; }; int main() { try { D val; } catch(...) { } }上記の例の出力は、以下のとおりです。
~B() called Handler of function try block of D(): Exception in D()D() の関数 try ブロックのハンドラーに入ると、 ランタイムは、まず最初に D の基底クラスのデストラクター、 つまり B を呼び出します。 val が完全に構成されていないので、D のデストラクターは呼び出されません。
#include <iostream> using namespace std; class E { public: const char* error; E(const char* arg) : error(arg) { }; }; class A { public: A() try { throw E("Exception in A()"); } catch(E& e) { cout << "Handler in A(): " << e.error << endl; } }; int f() try { throw E("Exception in f()"); return 0; } catch(E& e) { cout << "Handler in f(): " << e.error << endl; return 1; } int main() { int i = 0; try { A cow; } catch(E& e) { cout << "Handler in main(): " << e.error << endl; } try { i = f(); } catch(E& e) { cout << "Another handler in main(): " << e.error << endl; } cout << "Returned value of f(): " << i << endl; }上記の例の出力は、以下のとおりです。
Handler in A(): Exception in A() Handler in main(): Exception in A() Handler in f(): Exception in f() Returned value of f(): 1
#include <cstdio> using std::printf; int global_argc; struct A{ int _x; A(); A(int); }; A::A(int x):_x((printf("In A::A(int) initializer for A::_x.¥n"),x)){ printf("In A::A(int) constructor body.¥n"); if(global_argc % 2 !=0){ printf("Will throw.¥n"); throw 0; } printf("Will not throw.¥n"); } A::A() try:A((printf("In A::A() initializer for delegating to A::A(int).¥n"),42)){ printf("In A::A() function-try-block body.¥n"); } catch(...){ printf("In catch(...) handler for A::A() function-try-block.¥n"); } int main(int argc, char **argv){ printf("In main().¥n"); global_argc = argc; try{ A a; printf("Back in main().¥n"); } catch(...){ printf("In catch(...) handler for try-block in main().¥n"); } return 0; }この例は、生成されるプログラムの呼び出し時に受け渡される引数の数に応じて、異なる出力を生成できます。 引数が偶数個の場合、例外がスローされます。出力は次のとおりです。
In main(). In A::A() initializer for delegating to A:A(int). In A::A(int) initializer for A::_x. In A::A(int) constructor body. Will throw. In catch(...) handler for A::A() function-try-block. In catch(...) handler for try-block in main().引数が奇数個の場合、例外はスローされません。出力は次のとおりです。
In main(). In A::A() initializer for delegating to A::A(int). In A::A(int) initializer for A::_x. In A::A(int) constructor body. Will not throw. In A::A() function-try-block body. Back in main().
詳細については、委任コンストラクター (C++0x)を参照してください。