例外の使い方

id:peregrination:20060129が例外で迷ってるらしいので、書いてみる。
コメントには、書ききれそうにないので。

結論としては、例外はエラーの通知に使うと便利ってこと。

実行が中止される

例外が投げられる(throw)と、その場でどんどん上位に伝わっていく。

f1();
f2();  // 例外が発生
f3():  // この関数は実行されない

だから、いちいち返り値をみて、エラーが生じているか調べる必要がない。


これの一番身近な例は、CのmallocC++のnew。
mallocはメモリが確保できないとNULLが返るだけだから、毎回チェックしなければいけない。

char* buffer = (char*)malloc(sizeof(char) * 256);
if(buffer == NULL){
 return -1;
}
.....

でも、newはメモリが確保できないと例外が発生するので、普段は気にしないでもいい。

char* buffer = new char[256];  // 確保できないと、例外が発生する
....

(newは例外じゃなくて、専用のハンドル関数を用いていた気がするけど、まあいいや。)

伝播する

もう一つの利点は、例外は捕捉(catch)しないかぎりどんどん上位に伝わること。
だから、エラーが起きても、いちいちエラーコードをreturnしなくてもよくなる。

例外がない場合。

int f(){
  // エラーが起きたら-1を返す関数
  ....
  if(some_error()){
    return -1;
  }
  .....
}
int g(){
 ....
 if(f() == -1) {
   return -1;
 }
 ....
}
int main(){
 ....
 if(g() == -1) {
   printf("*****error***");
   return -1;
 }
 ....
}

これを例外を使って書き直すと、

void f(){
  ....
  // エラーが起きたら、例外を投げる
  if(some_error){
     throw "error";
  }
  ....
}
void g(){
  ...
  f();  // 普通に使える
  ...
}
int main(){
  try{
    g();
  }catch{
    printf("***error***');
    return -1;
  }
}

コードを見るとわかるように、例外を投げる関数と捕捉する関数以外は、エラー処理を気にしなくてすむ。
だから、うっかりエラー処理を書き忘れる心配もなくなる。

参考文献

例外といえば、この本なので一応紹介。

Exceptional C++―47のクイズ形式によるプログラム問題と解法 (C++ in‐Depth Series)

Exceptional C++―47のクイズ形式によるプログラム問題と解法 (C++ in‐Depth Series)

  • 作者: ハーブサッター,浜田光之,Harb Sutter,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/11
  • メディア: 単行本
  • 購入: 9人 クリック: 134回
  • この商品を含むブログ (63件) を見る
Modern C++ Design(ISBN:4894714353)と対をなして、C++最難関とか言われてる本。別にそんな印象は受けなかったけど。

例外についての話題がいっぱい(例外中立・例外安全など)。ただし、これを読んでいるといままで自分の書いていたコードが恥ずかしくなるので注意。