#include #include #include using std::cout ; using std::endl ; using std::string ; // class E { // 投げられる例外クラス。 例外をすり替えた時に何が起こるかの確認用。 int m_e ; string m_name ; public: E( int e = 1 ): m_e(e), m_name("E") { cout << " E() : " << m_name << "のコンストラクト" << endl ; } E( const E& e ): m_e(e.m_e), m_name(e.m_name + "のコピー") { cout << " E(E&) : " << m_name << "のコンストラクト" << endl ; } ~E(){ cout << "~E() : " << m_name << "のデストラクト" << endl ; } void show(char* msg="") const { cout << msg << m_name << " (" << m_e << ")" << endl ; } operator int() const {return m_e ;} } ; // class Cthrow { // コンストラクタ中で例外を発生させてみるテスト bool m_isThrow ; public: Cthrow( bool isThrow = false ): m_isThrow(isThrow) { cout << " Cthrow(" << isThrow << ")" << endl ; if (isThrow) { throw E() ; } } ~Cthrow(){ cout << "~Cthrow(" << m_isThrow << ")" << endl ; } } ; // class Ccatch { Cthrow m_a ; Cthrow m_b ; public: Ccatch( bool a = false, bool b = false ) try : m_a(a), m_b(b) // 初期化子中で例外を発生させてみるテスト { cout << " Ccatch()" << endl ; } catch (E& e) { // 初期化子中で発生した例外を補足するテスト e.show(" Ccatch() : exception : ") ; // コンストラクタの関数 try ブロックのハンドラの最後では、例外が再 throw される。 // ISO/IEC FDIS 14882:1998(E) : Programming Languages - C++ // 15.3 - Handling an exception [except.handle] // -16- The exception being handled is rethrown // if control reaches the end of a handler of the function-try-block of a constructor or destructor. // Otherwise, a function returns when control reaches the end of a handler for the function-try-block. // # ↑の仕様を知らなかったので、クラス名を Ccatch ってしちゃった。 看板に偽り有りだね。 // // throw 'e' ; // 別の例外にすり替えるのはアリみたい。元の例外クラスのデストラクタもちゃんと動く。 // // ISO/IEC FDIS 14882:1998(E) : Programming Languages - C++ // 15.3 - Handling an exception [except.handle] // -15- If a return statement appears in a handler of the function-try-block of a constructor, the program is ill-formed. // だって。試してみよう。 // return ; // おお、ほんとにコンパイルエラーになった。 } catch (...) { cout << " Ccatch() : unknown exception occurred." << endl ; } ~Ccatch(){ cout << "~Ccatch()" << endl ; } } ; // void try_catch_test() try { cout << "try_catch_test() : BEGIN." << endl ; Ccatch(false, true) ; cout << "try_catch_test() : END." << endl ; } catch (E& e) { // コンストラクタの関数 try ブロックのハンドラから再 throw された例外はここで catch される。 e.show("try_catch_test() : exception : ") ; // コンストラクタでもデストラクタでも無い関数の関数 try ブロックなので、 // 例外の再 throw はされない。 return ; // コンストラクタでは無いので、return がエラーにはならないことの確認をしてみるテスト。 } catch (...) { cout << "try_catch_test() : unknown exception occurred." << endl ; } // int main() try { try_catch_test() ; cout << "Hello, GCC." << endl ; return 0 ; } catch (E& e) { e.show("exception : ") ; exit(e) ; } catch (...) { cout << "unknown exception occurred." << endl ; exit(-1) ; } /* [実行結果] D:\wk\c++\try_catch>gcc -dumpversion 3.2.3 D:\wk\c++\try_catch>gcc try_catch_001.cpp -lstdc++ D:\wk\c++\try_catch>a try_catch_test() : BEGIN. Cthrow(0) Cthrow(1) E() : Eのコンストラクト E(E&) : Eのコピーのコンストラクト ~E() : Eのデストラクト ~Cthrow(0) Ccatch() : exception : Eのコピー (1) try_catch_test() : exception : Eのコピー (1) ~E() : Eのコピーのデストラクト Hello, GCC. D:\wk\c++\try_catch> */