プロが教える店舗&オフィスのセキュリティ対策術

プログラミング超初心者です。
現在、C++やjavaの勉強をしているのですが、
・try~catchとはなんぞや
・どんな処理をするときにtry~catchをつけなければいけないのか
がよくわかっていないので、教えていただけないでしょうか?
また、そういったことが載っているサイトも併せて教えていただければうれしいです。

A 回答 (4件)

例外エラーが発生する可能性がある場合に利用します。


基本的に、tryで正常処理を行い、catchで例外エラーをキャッチしてエラー処理を行います。

Javaだと、仮にこんなプログラム
public class test {
public static void main(String[] args) {
try {
String[] hoge = new String[] {"abc", "def", "ghi"};

for(int i = 0; i <= hoge.length; i++) {
System.out.println(hoge[i]);
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("例外エラーが発生した場合に処理する");
System.out.println("配列要素の不足");
e.printStackTrace();
} finally {
System.out.println("正常終了、例外エラー、どちらの場合でも必ず最後に処理する");
System.out.println("処理の終了");
}
}
}
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
サンプルコードまで載せていただいて、参考になりました。

お礼日時:2007/03/19 09:25

同じく初心者ですが、おおまかに「予測不可能なエラー」対応に try/catch を使用します。


例えば、ファイルが存在しないとか、ユーザーが許容範囲を越える文字列を入力したとかは「予測可能」なので通常の if/else で対応して、
例えば、データベースとの接続が途中で切断されるなどは「予測不可能」なので try でつかまえて catch 節の中で対応する。その箇所で対応不能なら再度例外を throw する。

人によっては、ファイルの存在を確認せずにオープンしてみて、「ファイルが存在しない例外」を catch するようなコーディングをするかも知れませんが、私は好きでない。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
「予測可能」 =if/else
「予測不可能」=try/catch
ということですが、いかんせん初心者なもんで「予測可能」と「予測不可能」の違いがいまいちわかっていません。
データベースとの接続が途中で切断されるのは「予測不可能」となっていますが、それは、いつそんな事態が発生するかなんて「予測不可能」である、という意味でしょうか?

せっかく教えていただいたのに何だかすいません。
勉強あるのみですかね・・・。

お礼日時:2007/03/19 09:50

Javaはまだましですが、C++の場合、ありとあらゆる箇所で例外が送出される可能性があります。

特にテンプレートを使った場合は、普通に演算子を使っただけでも例外に配慮する必要があります。

では、try~catch(正確には「監視ブロック(try-block)」といいます)は具体的にどんなところで使うかですが、送出された例外を処理することができる箇所、または他の例外に置換すべき場所で使用します。

送出された例外を処理することができない箇所に監視ブロックを入れてみても、どうすることもできずに、(臭いものに蓋をするように)単に例外を捨ててみたり、abort等で異常終了させるしかなくなります。例外が発生したときに、リソースの解放や状態の巻き戻しを行うためだけであれば、監視ブロックではなくデストラクタを使うべきです(Javaなら仕方ないでしょうが)。

別の例外に置換すべき場合というのは、モジュールの内部で発生した例外を外部に通知する場合に、実装の詳細に依存した例外から外部とのインタフェース用の例外に治してあげる必要がある場合などです。

例外処理というと、単に監視ブロックの使い方だけだと誤解されがちですが、実際には監視ブロックを使わない箇所での例外の扱いの方がずっと難しかったりします。「例外安全」または「exception safe」というキーワードで検索すれば、ある程度情報が得られるかと思います。
    • good
    • 0

これは、「例外処理」のためのものです。


動きとしては、
try { ... } の中で発生した「例外」に対する処理を、 catch { ... } の中に記述しますということになります。
これは、例外(おおざっぱに言えば、内部的なエラー)の「発見」と「発生」と、「リカバリ」に関わる分離の思想から考えられたものです。

例外処理がない場合、エラーの処理は、
・エラーが発生してないかどうか確認する
・エラーが発生していたら、その場で処理する
ということになります。

この方法には、問題がああって、本来の処理とエラー処理が混在して処理の見通しが悪くなるということになります。
例えば、以前の(失敗したら NULL を返す仕様の new 演算子の場合)

classA a = new classA(1, 0);
if (a == 0)
goto エラー処理;
classA b = new classA(1, 1);
if (b == 0)
goto エラー処理;
など。
これに対して、最近の(失敗したら、bad_alloc 例外をスルーする ) new だと、

try
{
classA a = new classA(1, 0);
classA b = new classA(1, 1);
}
catch(bad_alloc) // これは、new で失敗した時に投げられる例外
{
エラー処理
}

となります。
こうすれば、if (a == 0) が本来の処理ではなく、エラーチェックだったのがわかります。

また、往々にして、エラーの検出箇所(それがエラーだったとわかる場所)と、エラーの発生場所(エラーを発生させてしまった場所)は違うものです。

例えば、平方根を算出する関数はマイナスの引数を受け付けません。このため、普通は関数の中で引数がマイナスでないかどうかチェックをします。
おかしな引数を渡していれば、関数の中で引数がおかしいかどうかわかります。
しかし、この間数の中では、なぜ引数がおかしいのかはわかりません。
入力ミスなのか、計算ミスなのか。

一方で、引数がおかしくなった原因は、この間数を呼び出す箇所(の近く)にあることが多いわけです。
ですから、おかしな引数のリカバリは、こちら(発生場所)で行う方が妥当です。

もちろん、関数を呼び出す前にあらかじめ引数の妥当性をチェックするというのも正しい考え方です。
ただ、場合によっては、通常処理の流れでプログラムを作り、その処理の中で(この部分を try で囲む)エラーが検出された箇所(実際には、例外処理がスルーされる場所)の情報をもとに、エラーのリカバリ(ここが、catch セクション)を行うという形にするとすっきりする場合があります。
    • good
    • 2

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!