関数またはコンストラクターのパラメーターのスコープおよび存続期間が、
関数 try ブロックのハンドラーにまで適用されます。
次の例は、このことを示しています。
void f(int &x) try { throw 10; } catch (const int &i) { x = i; } int main() { int v = 0; f(v); }
main() の関数 try ブロックは、 静的ストレージ期間を持つオブジェクトのデストラクター、 またはネーム・スペース・スコープ・オブジェクトのコンストラクターで、スローされる例外をキャッチしません。
次の例は、静的オブジェクトのデストラクターから例外をスローします。
#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 ブロック・ハンドラー内に置くことはできません。
オブジェクトのコンストラクター、またはデストラクターの関数 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 のデストラクターは呼び出されません。
ランタイムは、コンストラクターまたはデストラクターの関数 try ブロックのハンドラーの終了時に、 例外を再スローします。 その他のすべての関数は、関数 try ブロック・ハンドラーの終了に到達した時点でリターンします。 次の例は、このことを示しています。
#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
関連参照