今回は、前回のプログラムをもっと洗練させます。かなりすっきりしますよ。
それでは、今回の要点です。
では、いってみましょう。
goto を使うよりも綺麗になるといっておきながら、前回のプログラムは大して変わっていませんでした。今回は、そのあたりを考えてみたいと思います。
では、もういちど前回のプログラムを見てみましょう。
int Func() { FILE *pf1 = NULL; FILE *pf2 = NULL; FILE *pf3 = NULL; int fRet = 0; try { pf1 = fopen(szFile1, "r"); if(pf1 == NULL) throw 1; pf2 = fopen(szFile2, "r"); if(pf2 == NULL) throw 2; pf3 = fopen(szFile3, "w"); if(pf3 == NULL) throw 3; Func2(pf1, pf2, pf3); } catch(int fError) { fRet = fError; } if(pf1 != NULL) fclose(pf1); if(pf2 != NULL) fclose(pf2); if(pf3 != NULL) fclose(pf3); return fRet; } |
何が鬱陶しいかといえば、if 文です。goto の時もそうですが、これは一応マクロで簡単にすることができます。
しかし、例外はそんなものを使わなくてもいいのです。次のプログラムを見て下さい。
FILE* Open(const char* pszFile, const char* pszMode, int fError) { FILE *pf = fopen(pszFile, pszMode); if(pf == NULL) throw fError; return pf; } int Func() { FILE *pf1 = NULL; FILE *pf2 = NULL; FILE *pf3 = NULL; int fRet = 0; try { pf1 = Open(szFile1, "r", 1); pf2 = Open(szFile2, "r", 2); pf3 = Open(szFile3, "w", 3); Func2(pf1, pf2, pf3); } catch(int fError) { fRet = fError; } if(pf1 != NULL) fclose(pf1); if(pf2 != NULL) fclose(pf2); if(pf3 != NULL) fclose(pf3); return fRet; } |
何か Open という関数を作っていますね。で、例外はこの Open の中で投げています。一方、try ブロック内には throw は見あたりません。しかし、try ブロック内から Open を呼んでいます。
もう分かりましたね。try ブロック内の関数の中で例外が投げられても catch できるのです。Open 内で投げられた例外が、関数外にまで届いているとも言えますね。
このように、例外は関数外にまで届きます。これが例外処理の強力たる所以です。これでだいぶすっきりしました。
では、try ブロックがないのに例外が投げられたらどうなるのでしょうか? 早速やってみましょう。
プログラム |
---|
// Except1.cpp int main() { throw 1; return 0; } |
実行結果例 |
abnormal program termination |
問答無用なプログラムですね(笑)。
結果はいろいろありますが、とにかくエラー終了します。環境によってはそこからデバッグを開始できたりします。
最後に。ファイルを開くのに関数を作り、ファイルを読み込むのに関数を作り、というのは一見面倒に見えます。ですが、実は CFile クラスを作るときにそれは済ませていますね。CFile クラスの関数を、エラー時に例外を投げるように改造してしまえばいいのです。
// ファイルを開く void CFile::Open(const char* pszFile, const char* pszFlags) { Close(); char bufFlags[8]; if(ModifyFlags(pszFlags, bufFlags, numof(bufFlags)) == false) return false; m_pfile = fopen(pszFile, bufFlags); if(m_pfile == NULL) throw 1; } bool Func() { CFile file1, file2, file3; try { file1.Open(szFile1, "r"); file2.Open(szFile2, "r"); file3.Open(szFile3, "w"); Func2(file1, file2, file3); } catch(int fError) { return false; } return true; } |
これでずいぶんとすっきりしましたね。ファイルのクローズがデストラクタで行われるので、そこら辺せこい気もしますが。
それでは、今回の要点です。
例外処理の機能はまだまだあります。ぼちぼちとやっていきましょう。
それでは。
Last update was done on 2001.2.27
この講座の著作権はロベールが保有しています