14項 例外使用を賢く用いる
例外使用を賢く用いる
C++標準では、関数がthrow一覧にない例外をスローした場合unexpectedを呼び出す必要があります。
void throwAnyType() throw(...) { throw "string"; } void noThrow() throw() { throwAnyType(); //unexpected() }
unexpectedのデフォルトの振る舞いはterminate()を呼び出すことなので、デフォルトのunexpectedを呼び出してはいけません。
対策は、unexpectedを上書きし、terminateを呼び出させないことです。unexpectedは、set_unexpected()で上書きできます。
unexpectedが投げる例外を指定して、処理するという方法があります。
class UnexpectedException{}; void convertUnexpected(){ throw UnexpectedException();} set_unexpected(convertUnexpected); //unexpectedはconvertUnexpectedになる。
unexpectedの代替関数が例外を投げなおすとき、その例外はbad_exceptionになるというルールがあります。
そのルールを利用して、unexpectedが投げる例外をbad_exceptionに固定できます。
void convertUnexpected(){ throw ;} //bad_exceptionを投げる。 set_unexpected(convertUnexpected);
あとは投げられた例外を処理することで、安全を保てます。
Visual C++での実装
MSDN:unexpectedの解説の部分に、
C++ 標準では、関数が throw 一覧にない例外をスローした場合 unexpected を呼び出す必要があります。 現在の実装では、これをサポートしていません。
とあるため、現在のVisual C++ではunexpectedが呼び出されません。なので、unexpectedからterminate()が呼ばれる心配はありません。