ホームに戻る
関連 :
目次 :
例外処理(exception handling)とは
実行時エラーを管理し、処理する機構。
エラー(例外)発生時の処理を体系的に、また集約して実装することができる。
C++に限らず、オブジェクト指向言語においては一般的な概念。
尚、例外を発行することを慣例的に「例外を投げる(throw exception)」という。
例外処理の原則
C++における例外処理の原則は以下の通りである。
- 例外(エラー)の発生を監視したい処理を try 節内に記述すると、例外が発生した場合即座に try 節を抜け、直後の catch 節にジャンプする。
- try 節内における、例外発生箇所より後の処理は実行されない。
- catch 節は必ず try 節の直後に記述する必要がある。
- catch 節では宣言した型の例外のみ捕捉可能。複数の catch 節を書き連ねることで、発生した例外の型に応じて後処理を区分できる。
- 即ち、実行される catch 節は最大でも1つ。
- 捕捉できない型の例外が発生した場合は、プログラムが不正終了する。
- catch 節以降に処理が存在する場合、例外が発生しなければ try 節実行後、例外が発生すれば catch 節実行後に実行される。
- システム内部で発生する例外以外に、throw 句を用いることで任意の例外を発生させる(投げる)ことができる。
基本的な例

上記の例では、関数 func() 中の try 節に含まれる func2() 、DoSomething() が例外監視対象となる。
func2() では内部で int 型例外を投げ( throw )ており、try 節に続く catch (int ex) 節で例外が捕捉される。
(int 型と異なる型の例外が投げられた場合は、後続の catch (string ex) 節、または catch (...) 節で捕捉される。)
例外の投げなおし
try ブロックで発生した例外を処理した後、さらに外側に例外を投げることができる。
当然、try ブロックは(コールスタック全体で)ネストしている必要がある。
捕捉した例外と異なる例外を投げる

catch 節内に throw 句を記述することで、さらに外側に例外を投げる。
このとき、捕捉した例外と型や値が一致している必要はない。
捕捉した例外をそのまま投げなおす
捕捉した例外をそのまま投げなおす場合は、throw のみを記述する。
void func1()
{
try
{
// ここで例外発生
func2();
}
catch (exception ex)
{
// 例外を投げなおす
throw;
// これは誤り
// throw ex;
}
}
上記のコードでは例外 ex を捕捉し、外側に投げなおしている。
このときthrow ex;
とすると、ex が投げられた時点でのコールスタック情報( func2() )しか記録されないため、
func1() が例外を投げ(なおし)たことがわからなくなる。
単にthrow;
とすることで、投げなおした func1() の情報も追加される。
投げなおされる例外の型は ex と共通である。
例外送出有無の表明 ( noexcept )
noexcept 句を使用することで、関数が例外を送出しない(または逆に、する可能性がある)ことを明確化することができる。
例外を送出しないことを明示すると巻き戻すためのスタックが確保されなくなるため、スタック使用量を削減することができる。
// 例外を送出しない
void f() noexcept;
void f() noexcept(true);
// 例外を送出する(可能性がある)
void f() noexcept(false);
void f();
過去には、throw 句を用いて送出例外の型を制限する記法も存在したが、これはあまり有用ではないことから
C++11で非推奨となり、C++17で削除された。
C++標準の例外クラス
C++の標準ライブラリには、例外として送出するためのクラス(例外オブジェクト)が定義されている。詳細はここを参照。