Loose-Info.com
Last Update 2023/12/20
TOP - 各種テスト - C++ - 例外処理

概要

try、throw、catch 各ステートメントの動作確認
例外処理における例外オブジェクトの生成・破棄に関するテスト
例外指定 noexcept を指定した関数を含むコードのコンパイル結果


try、throw、catch 各ステートメントの動作確認


sample.cpp
#include <iostream> struct Smpl { }; template<class T> void f(T x) { // tryステートメント try { // throwステートメント throw x; } catch (T) // 例外ハンドラ(型が一致した場合に処理) { // 本来はここで例外処理 std::cout << "catch : " << typeid(T).name() << std::endl; } } int main() { Smpl s; // 動作確認のため型引数を変えて関数テンプレートを呼び出し f<int>(1); f<double>(2.34); f<const char *>("sample"); f<Smpl>(s); f<long double>(1.23456789012345678L); }

実行結果
$ gcc -Wall sample.cpp -lstdc++ $ ./a.out catch : i catch : d catch : PKc catch : 4Smpl catch : e (注) typeid(T).name()で出力される型を示す文字は実装依存

例外処理における例外オブジェクトの生成・破棄に関するテスト


sample.cpp
#include <iostream> struct Smpl { // コンストラクタ Smpl() { std::cout << "Constructor : " << this << std::endl; } // コピーコンストラクタ Smpl(const Smpl& rs) { std::cout << "Copy Constructor : " << this << std::endl; } // デストラクタ ~Smpl() { std::cout << "Destructor : " << this << std::endl; } }; struct Smpl2 : public Smpl {}; template<class T> void f(T& x) { try { std::cout << "[thorw s] start : " << &x << std::endl; throw x; std::cout << "[thorw s] end : " << &x << std::endl; // 実行されない } catch (const Smpl2 e) { std::cout << "[catch Smpl2] : " << &e << std::endl; } catch (const Smpl& e) // 参照によるキャッチ { std::cout << "[catch Smpl&] : " << &e << std::endl; } } int main() { Smpl s1; Smpl2 s2; std::cout << std::endl; f<Smpl>(s1); std::cout << std::endl; f<Smpl2>(s2); std::cout << std::endl; std::cout << "[main()] end" << std::endl; }

実行結果
$ gcc -Wall sample.cpp -lstdc++ $ ./a.out Constructor : 0x7ffe3e8360cf Constructor : 0x7ffe3e8360ce [thorw s] start : 0x7ffe3e8360cf Copy Constructor : 0x1411340 <--- 例外オブジェクトをコピー初期化 [catch Smpl&] : 0x1411340 <--- スローされた例外オブジェクト Destructor : 0x1411340 <--- 例外オブジェクトの破棄 [thorw s] start : 0x7ffe3e8360ce Copy Constructor : 0x1411340 <--- 例外オブジェクトのコピー初期化 Copy Constructor : 0x7ffe3e836087 <--- 例外オブジェクトのコピーをコピー初期化 [catch Smpl2] : 0x7ffe3e836087 <--- スローされた例外オブジェクトのコピー Destructor : 0x7ffe3e836087 Destructor : 0x1411340 <--- 例外オブジェクトの破棄 [main()] end Destructor : 0x7ffe3e8360ce Destructor : 0x7ffe3e8360cf

例外指定 noexcept を指定した関数を含むコードのコンパイル結果


sample.cpp
#include <iostream> struct Smpl0 { virtual void f1() noexcept; virtual void f2(); virtual void f3() noexcept; }; struct Smpl1 : public Smpl0 { void f1() { throw 1; }; // 基底クラスでnoexcept指定で仮想関数を宣言 void f2() { throw 1; }; void f3() noexcept { std::cout << "Smpl1::f3()" << std::endl; } // 基底クラスでnoexcept指定で仮想関数を宣言 }; void f1() noexcept { std::cout << "f1()" << std::endl; } // noexcept指定され、例外のスロー無し void f2() noexcept { std::cout << "f2()" << std::endl; throw 1; } // noexcept指定され、例外のスロー有り void f3() { std::cout << "f3()" << std::endl; throw 1; } // noexcept指定無しで、例外のスロー有り int main() { Smpl1 s1; s1.f1(); f1(); f2(); f3(); }

実行結果
$ gcc -Wall sample.cpp -lstdc++ sample.cpp:12:14: error: looser exception specification on overriding virtual function ‘virtual void Smpl1::f1()’ <--- 例外指定の緩和に関するエラー 12 | void f1() { throw 1; }; // 基底クラスでnoexcept指定で仮想関数を宣言 | ^~ sample.cpp:5:22: note: overridden function is ‘virtual void Smpl0::f1() noexcept’ 5 | virtual void f1() noexcept; | ^~ sample.cpp: In function ‘void f2()’: sample.cpp:18:56: warning: ‘throw’ will always call ‘terminate’ [-Wterminate] 18 | void f2() noexcept { std::cout << "f2()" << std::endl; throw 1; } // noexcept指定され、例外のスロー有り

実行環境

GNU bash, version 5.1.16
GCC-12.2.0
GNU C Library 2.36
GNU Binutils 2.39


コード例・出力内容中の表記

・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。