今回は、前回のプログラムをもっと洗練させます。かなりすっきりしますよ。
それでは、今回の要点です。
では、いってみましょう。
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
この講座の著作権はロベールが保有しています