Quantcast
Channel: アトムAPP研究室
Viewing all articles
Browse latest Browse all 88

[C++] 例外処理のメモ

$
0
0

例外処理に利用するクラスなどはヘッダをインクルードして使う。C++11 で追加された例外はどう使えばいいのかよくわからないけど、たぶん私のようなバカには無用のものだろうと思うのでまぁどうでもいいか…

std::runtime_error 例外処理

C++の標準の例外は全てstd::excpeption の派生クラス(stdexpectヘッダ参照)になっている。

参考 : C++編(標準ライブラリ) 第27章 例外クラス

C++は例外としてどんな型でも投げられる(voidは無理)けども
std::exception の派生クラスを普通は作る。

C++の例外はスタックトレースとか取れない。

またデストラクタから例外を送出してはならない。

[cpp] void thrower(bool b) throw(int) { if (b) { throw 100; } else { throw "not int"; } } int main() { try { throw std::runtime_error("TEST"); } catch (std::runtime_error e) { puts(e.what()); // TEST } try { throw nullptr; } catch (...) // どんな型でも受け取れる { puts("nullptr"); } try { thrower(true); } catch (const char *text) { puts(text); // ここは通らない } catch (int &i) { printf("%d\n", i); // 100 } try { thrower(false); // terminate called throwing an exception } catch (...) { puts("ココを通らずにプログラム実行終了"); } } [/cpp]

例外仕様の記述が無い場合にキャッチしないと関数外に送出されずに実行終了する。
ただし std::runtime_error は例外仕様を記述する必要がないっぽい。

noexpect (C++11)

noexpect は例外仕様で throw() と書いた場合と同じ効果。
noexpect(true) とか noexpect(noexpect(MyFunc()) とか

exception_ptr (C++11)

exception_ptrはあらゆる例外を保持できる。
current_exceptionは現在のcatchブロック内の例外を取得できる。
rethrow_exceptionはexception_ptrを再スローする。
make_exception_ptrでexception_ptrを生成できる

[cpp] std::exception_ptr ep; try { throw 123; } catch (...) { // int型などの例外でも current_exception で取得できる ep = std::current_exception(); } try { std::rethrow_exception(ep); // もっかい投げられる } catch (int e) { std::cout << e << std::endl; } // exception_ptr 自体を作る場合は make_exception_ptr std::runtime_error e("TEST"); ep = std::make_exception_ptr(e); try { std::rethrow_exception(ep); } catch (std::runtime_error e) { std::cout << e.what() << std::endl; } [/cpp]

nested_exception (C++11)

nested_exceptionは名前通り入れ子の例外であり多重継承のmixinとして利用する。

[cpp] // // nested_exceptionは // class E : public std::nested_exception { public: int tag; E(int tag) : tag(tag) {}; }; try { throw "TEST"; } catch (...) { try { throw E(1); } catch (E e) { std::cout << e.tag << std::endl; // 1 try { // 内包された例外を送出 e.rethrow_nested(); } catch (const char * text) { std::cout << text << std::endl; // TEST } try { // .nested_ptr() で内包された例外を取得可能 std::exception_ptr ep = e.nested_ptr(); std::rethrow_exception(ep); } catch (const char *text) { std::cout << text << std::endl; // TEST } } } // // catchブロック外で生成してもネストした例外は空 // try { throw E(2); } catch (E e) { if ( ! e.nested_ptr()) { std::cout << "no nested ptr" << std::endl; } } // // rethrow_if_nested は // nested_ptr であれば中身(ネストされた例外)を送出する // ネストした例外が無いとダメ // try { std::string foo = "foo"; std::rethrow_if_nested(foo); // 何もおこらない throw foo; } catch (std::string &foo) { // // throw_with_nested は // 引数が nested_ptr であればそのまま送出し // 引数が nested_ptr でなければ nested_ptrと引数の型を継承した派生クラスを送出する // なので継承できないクラスは throw_with_nested に渡せない // try { // ここで投げられる例外は nested_ptr でも runtime_error でも catch できる // foo をネストした例外が投げられる std::throw_with_nested(std::runtime_error("bar")); } catch (std::runtime_error &bar) { std::cout << bar.what() << std::endl; // bar try { std::rethrow_if_nested(bar); } catch (std::string &foo) { std::cout << foo << std::endl; // foo } } } [/cpp]

Viewing all articles
Browse latest Browse all 88

Latest Images

Trending Articles





Latest Images