例外がないC言語を書いていると、例外が無性に恋しくなるときがあるのですが・・・。ということで、主に例外がないC言語と比較しながら述べます。
例外を一切発生させないようにプログラミングできるかというと、できます。というよりもそれができなければ例外がないC言語でプログラミングはできないことになってしまいます。では、例外はあるとなぜ便利なのか、どういうふうに使えば良いのかを述べていきます。
###落ちたところや原因がわかる
ほとんどのプログラミング言語で0除算はしてはいけないことになっています。例外があるプログらミグ言語では0除算に対する例外を発生させるでしょう。では、C言語ではどうかというと、SIGFPEシグナルを発行してアプリ全体が落ちます。通常、そのとき、どの関数のどの行で何が起きたのかと情報は一切表示されません。(シグナルはわかりますが、原因が0除算であるかどうかまではわかりません)
※ C言語の0除算時の動作は未定義となっており、処理系によっては異なります。UNIX/Linuxの処理系ではシグナル発行する場合が多いです。
もし、例外であれば、キャッチしていない場合は同じようにアプリが落ちますが、デフォルト状態でどの場所でどのような例外が発生したかを表示します。これだけでも後から原因を調査する大きな手がかりになりますので、問題解決がスムーズに行えるようになります。
###自動で大域脱出
メモリ不足やファイルオープン失敗などその場ですぐに解決できないような問題が発生するときがあります。完全にアプリを落としてしまうと言うのもありますが、中には今の処理をキャンセルして、しばらく待ってからリトライするとか、別処理を走らせるとかが考えられます。
そこで問題となるのは、複数の関数呼び出しや入れ子のfor文の深いところで発生した時です。途中で失敗したら、最初の呼び出しや最初のforの外側に戻りたい場合があるでしょう。例外があれば、途中でキャッチしない限り、どこまでも自動で遡ります。リトライなどの処理をしたいところでキャッチして、例外に即した処理を追加すればうまくいくでしょう。
では、C言語だとどうするかというと、途中の関数呼び出しをすっ飛ばすためにlongjmpを使います。このlongjmp、使い勝手が良いとはとても言えません。また、for文の深いところから脱出するには悪名高きgotoを使います。gotoをなぜ避けるべきかはいろいろなところで述べられていますが、下手なgotoはスパゲッティ化を招きます。
※ gotoは書いてはいけないと言われていますが、例外の代わりに(というより例外がないので)gotoを使うことは正しい使用方法の一つです。ただ、それなりの上級者ではないと難しいため、初心者には安易に使うなと言った方がいいということです。
###問題が起こるかも知れないがわかる
C言語では、ファイルオープンや書き込みに成功したかどうかを確認するのはプログラマーの仕事です。それを忘れてしまうと突然アプリが落ちるなど、想定外のバグが発生します。
Javaではファイルオープン時などにIOExceptionが発生する可能性があります。これは必ずキャッチするか、メソッドにthrows IOExceptionをつけて例外が発生するかもと知らせる必要があります。このようにして、プログラマーに例外の処理を強制させ、失敗時の処理を忘れる等の不具合の原因を排除します。(この機能はJavaぐらいで、採用している言語は少ないです。また、Javaでも全ての例外が必須になっているわけではありません。)
さて、例外を使うよりはif文で分岐させたほうが・・・とありますが、まさしくその通りです。例外は本来、おきてはいけないことであり、そもそも発生させるべきではありません。また、例外処理自体がかなり重い処理のため、安易に頼るでべきでもありません。0かも知れない変数を除算する前に0になっていないかをチェックすること悪いことでも何でもなく、例外があるからしなくてもいいとか、例外に頼らなければならないということではありません。
しかし、IO関係は実際に読み書きなどしないとできるかどうかはわからないなど、事前にチェックすることは不可能な例外があります。また、本来はバグ以外で起きないよう動作、例えば配列でインデックスを越えてアクセス等は、事前チェックが冗長になってしまいます。そのようなときは、例外に頼ることは良い方法だと思います。あまり具体的な例を出せないで申し訳ないのですが、ここら辺は他のプログラム(入門書とかの無意味なサンプルではなく)がどのように書いているかとか見たり、自分で書いていく内に感覚が掴めるのではないかと思っています。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。