例外処理について考えた場合、string型やint型では多くのケースが
情報不足に陥る事になる。
そこで例外クラスを作成する事が一般的だと思います。
もの凄く汎用的なクラスを作成してしまえば
class base_error {
private:
int nRetCode, nDtlCode;
public:
base_error () { nRetCode = 0; nDtlCode = 0; }
base_error (int InRetCode, int InDtlCode) { nRetCode = InRetCode; nDtlCode = InDtlCode; }
void Print_ErrMsg() const {
cerr << "Error RET[" << nRetCode << "] DTL[" << nDtlCode << "]\n";
}
};
これは何の情報もないエラークラスです。
これを派生させて、様々なエラークラスを作成してしまえば良いのです。
なので全てのエラーの既定クラスとするbase_errorの「Print_ErrMsg」は
virtual宣言に変えておきましょう。
では派生させてみましょう。
「数値型」を受けるクラスのメソッドについて考えてみます。
このメソッドが引数に期待している値が「0~99」だとします。
その場合、引数に対して「0 <= 引数 <= 99」といったチェックが行われるでしょう。
そして、この条件が満たされなかった場合「Out Of Range」という事なり例外発生です。
このような場合、エラー情報として実際に何が引数に渡されたのかを出力するのが通常です。
class OutOfRange : public base_error {
private:
string strFuncName;
int nValue;
public:
OutOfRange (string InFuncName, int InValue) { strFuncName = InFuncName; nValue = InValue; }
void Print_ErrMsg() const {
cerr << strFuncName << "::OutOfRange value = [" << InValue << "]n";
}
};
これで完成です。
後はこれを捕捉すれば良い事になります。
ここでちょっとした工夫が必要になります。
単純に書けば
try {
func();
} catch (OutOfRange o) {
o.Print_ErrMsg();
}
とすれば良いのですが、もちろんこれは違います。
絶対的に違うのは、何のためにbase_errorを派生させたかって事です。
「OutOfRange」というクラスオブジェクトの時のみ特殊な動きが発生する場合
この方法もありますが、上は単純にエラーメッセージを出力しているのみです。
であれば、基底クラスである「base_error」で捕捉をするのが通常の方法です。
try {
func();
} catch (base_error o) {
o.Print_ErrMsg();
}
となります。
実は、これでも不十分となります。
何故なら、「base_error o」というように値で捕捉をしているからです。
値で捕捉しているという事は「o.Print_ErrMsg()」で出力されるのは
基底クラスの「Print_ErrMsg()」という事になりますね。
そのため、アドレスという形(参照で問題ありません)で捕捉をする必要があります。
try {
func();
} catch (base_error &o) {
o.Print_ErrMsg();
}
が期待している形になります。
後は、様々な例外クラスを派生クラスという形で作成していく事で
ある規則に従って記述されたメイン処理は余す事なく例外を捕捉出来る事になります。
0 件のコメント:
コメントを投稿