More Effective C++ 項目14 例外仕様を賢く用いる
新訂版 More Effective C++ (AddisonーWesley professional co)
- 作者: スコット・メイヤーズ,安村通晃,伊賀聡一郎,飯田朱美,永田周一
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2007/06/29
- メディア: 単行本(ソフトカバー)
- 購入: 8人 クリック: 129回
- この商品を含むブログ (43件) を見る
項目14 例外仕様を賢く用いる
関数が例外仕様にない例外を発生させたとき、特別な関数unexpectedが自動的に起動される。
unexpectedの省略時の振る舞いはterminateを呼ぶことで、terminateの省略時の振る舞いはabortである。
abortは後片付けを行わずにプログラムを停止するので、例外仕様の違反は起こしてならない。
例外仕様を含まない関数f1を考える。
extern void f1(); // 何でも投げる
関数f2はint型例外が発生しうることを宣言。
void f2() throw(int);
次のように書いてもC++としては正しい。
void f2() throw(int) { ... f1(); // f1はint以外の例外を投げるかも ... }
コンパイラは文句を言わないが、例外が発生するとプログラムが停止するため、こういった例外仕様の矛盾を最小限にする必要がある。
テンプレートと例外仕様は混ぜない
template<class T> bool operator==(const T& a, const T& b) throw() { return &a == &b; }
このテンプレートは、全ての型にoperator==を定義し、アドレスを比較している。
このテンプレートから生成される関数は例外を発生しないという例外仕様だが、operator&は型によってはオーバーロード可能であり、例外を発生させる可能性がある。
テンプレートの型引数からは例外が発生するかどうかはわからないため、型引数をとるテンプレートに例外仕様をつけてはいけない。
例外仕様を持たない関数を呼ぶ関数には、例外仕様をつけない
例外仕様つきの関数ポインタをtypedefする話だったが、typedefには例外仕様を含めないと標準委員会が宣言したらしく、本に載っている方法は使えないようだ。
省略する。
システムが発生させる例外を扱う
例外仕様を厳密に扱ったソフトを書いているとき、例外仕様を使っていないライブラリを使うとき、予期せぬ例外を予防するためには別の型の例外に変換する。
class UnexpectedException(); // 全ての予期しない例外をこれに置き換える void convertUnexpected() { // 予期しない例外が発生したとき呼ばれる関数 throw UnexpectedException(); }
省略時のunexpected関数を置き換える。
set_unexpected(convertUnexpected);
これで予期せぬ例外は型UnexpectedExceptionの例外になる。
また、unexpected関数の代替関数が現在の例外を発生させなおすと、bad_exceptionになる。
void convertUnexpected() { // 予期しない例外が発生すると現在の例外を投げる throw; } set unexpected(convertUnexpected); // unexpectedの代わりにconvertUnexpectedを使う
これで予期せぬ例外にであっても、bad_exceptionに置き換えられ、プログラムが停止することを防げる。