| 例外処理 |
例として、ファイル例外を発生させてみる。
void CUKExceptionDlg::GetFile()
{
try
{
CFile f("d:\\My Documents\\abc.txt", CFile::modeRead); // …(1)
……
AfxMessageBox("OK");
}
catch(CFileException* e)
{
if( e->m_cause == CFileException::fileNotFound )
AfxMessageBox("指定されたファイルは存在しません。");
else
AfxMessageBox("ファイル例外が発生しました。");
e->Delete();
}
}
上記のような関数を作成し、まず(1)の第1引数に実在するファイル名を指定して実行すると、
"OK"と書かれたメッセージボックスが表示されるはずである。
これは正常に処理がおこなわれたため、tryステートメント内で例外が発生せずにステートメントの最後まで達したことを示す。
次に(1)の第1引数を実在しないファイル名に変更して実行すると、
"指定されたファイルは存在しません"と書かれたメッセージボックスが表示される。
これは(1)で存在しないファイルを指定したために例外が発生し、catchステートメントへ処理が移行したことを示している。
catchステートメントの()内に指定された"e"は、生成されたファイル例外オブジェクト(CFileException)へのポインタであり、
このファイル例外オブジェクトのm_causeメンバを見ることで、
どのような原因で例外が発生したか、より詳細に調べることができる。
CFileExceptionはCExceptionの派生クラスであり、他にもCResourceExceptionなど例外の種類によって様々なクラスが用意されている。
また、catchステートメントの最後に
e->Delete();という一文があるが、例外オブジェクトはこのようにして削除する必要があるので忘れないこと。
try
{
GetFile();
}
catch(CFileException* e)
{
AfxMessageBox("GetFile関数で例外発生!");
e->Delete();
}
この場合、GetFile関数を全く変更せずに実行した場合、例外が発生するとGetFile内で例外処理がおこなわれ、
"GetFile関数で例外発生!"というメッセージボックスは表示されない。
void CUKExceptionDlg::GetFile()
{
try
{
……
}
catch(CFileException* e)
{
if( e->m_cause == CFileException::fileNotFound )
AfxMessageBox("指定されたファイルは存在しません。");
else
AfxMessageBox("ファイル例外が発生しました。");
throw; // ここを書き換える
}
}
このようにすることで、高い階層のcatchブロックに対して例外を再スローすることができるようになる。