DATE : 2006/10/22 (Sun)
Java では、throw 文を使って例外を投げることができます。(例では、NullPointerException を投げています)
throw new NullPointerException();
そして、catch 文で例外をキャッチできます。(例では、function メソッドで発生する NullPointerException をキャッチします)
try { function(); } catch (NullPointerException e) { // 例外用の処理 }
C++ にも例外機構があります。Java の場合は java.lang.Throwable を継承しているクラスのみ投げることができますが、C++ の場合はどのような型でも例外オブジェクトとして送出することができます。
例えば、次のコードは、例外オブジェクトとして int 型の1を送出します。
throw 1;
この例外を受け取るコードを書くと、次のようになります。この例では、function 関数の中に上の throw 文があるものと仮定しています。
try { function(); } catch (int e) { // 例外用の処理 }
受け取った値を使用しない場合は、変数名(上の例では「e」)を省略できます。
オブジェクトを送出することもできます。
try { throw Object(); } catch (Object& e) { // 例外用の処理 }
ここで、Object オブジェクトは new で生成しないようにします。new で生成してしまうと、生成したオブジェクトを解放し忘れてしまう場合があります。
また、受け取るときは参照で受け取るようにします。
なお、catch 文を複数連ねると、複数の例外に対応できます。つまり、投げられた例外に応じた catch 文が呼び出されます。
ちなみに、次のようにすると、どのような型でも受け取ることができます。
try { function(); } catch(...) { // 例外用の処理 }
(;^ω^)Java の catch(Exception e) { } のようなものですね
なお、catch 文の中で次のように throw 文を記述すると、受け取ったものと同じ例外を送出することができます。
try { function(); } catch(int e) { // 例外用の処理 throw; }
(;^ω^)Java の場合は、catch (Exception e) { throw e; } ですね。
なお、例外機構によって呼び出し元の関数に戻っていく過程では、スタックが次々と巻き戻されていきます。その際、スタック上に確保されていたオブジェクトは解放されますが、ヒープ上に確保されていたオブジェクトは解放されません。そのため、呼び出し元に戻る過程にあるヒープ上のオブジェクトは、上の方法を使って解放するようにします。
Object* obj = new Object(); try { function(); } catch(...) { // 受け取った例外は呼び出し元に投げる delete obj; throw; }
なお、標準 C++ ライブラリには、std::exception という、例外を表すオブジェクトがあります。
(;^ω^)こちらは、Java の Exception (RuntimeException)クラスのような働きをしてくれます。ちなみに、Java のような finally 文はありません。また、チェック例外もありません。
参考文献
- C++編(言語解説) 第25章 例外機構
- C++ プログラミングガイド 5.例外処理
- C++ の例外処理について
- Hey! Java Programming! C++言語 例外処理
- C++編(標準ライブラリ) 第27章 例外クラス