例外処理 : 古いコードの変換
これは高度なトピックです。
この記事では、Microsoft Foundation Class のマクロ (TRY、CATCH、THROW など) で書かれた既存のコードを変換し、C++ の例外処理キーワード try
、catch
、throw
を使用する方法について説明します。 ここでは、次の内容について説明します。
変換の利点
MFC バージョン 3.0 におけるマクロの実装とそれ以前のバージョンにおける実装とでは、違いがあるとわかっていても、ほとんどの場合、既存のコードを変換する必要はありません。 これらの違いと、その結果コードの振る舞いに生じる変化については、「例外: Version 3.0 での例外マクロの変更点」で説明されています。
変換の主な利点は次のとおりです。
C++ 例外処理キーワードを使用したコードの方が、コンパイル後の .EXE または .DLL のサイズがやや小さい。
C++ 例外処理キーワードの方が汎用性が高い: コピーできる任意のデータ型 (
int
、float
、char
など) の例外を処理できるのに対し、マクロで処理できるのは、CException
クラスとそこから派生したクラスの例外に限られます。
マクロとキーワードの大きな違いは、マクロを使用したコードでは、キャッチされた例外が、スコープから抜けた時点で "自動的に" 削除されるという点です。 キーワードを使用したコードでは、そのようなことは行われないので、キャッチされた例外は明示的に削除する必要があります。 詳細については、「例外処理 : 例外のキャッチと削除」の記事を参照してください。
もう 1 つの違いは構文です。 マクロとキーワードの構文は、次の 3 つの点が異なります。
マクロの引数と例外宣言:
CATCH マクロの呼び出し構文は次のとおりです。
CATCH(exception_class, exception_object_pointer_name)
クラス名とオブジェクト ポインター名との間にコンマが置かれていることに注目してください。
catch
キーワードの例外宣言には、この構文が使用されます。catch(exception_typeexception_name)
この例外宣言ステートメントは、catch ブロックで処理する例外の型を表しています。
catch ブロックの区切り:
マクロでは、CATCH マクロ (とその引数) で先頭の catch ブロックを、また、AND_CATCH マクロで後続の catch ブロックを開始して、END_CATCH マクロで一連の catch ブロックを終了します。
キーワードでは、
catch
キーワード (とその例外宣言) で各 catch ブロックを開始します。 END_CATCH マクロに相当するものはありません。catch ブロックは、対応する右中かっこで終了します。throw 式:
マクロでは、THROW_LAST を使用して現在の例外を再スローします。 同じ効果は、引数なしの
throw
キーワードで得られます。
変換の実行
マクロが使用されているコードを C++ 例外処理キーワードを使用するように変換するには
MFC のマクロ (TRY、CATCH、AND_CATCH、END_CATCH、THROW、THROW_LAST) が使われている箇所をすべて特定します。
次のマクロはすべて置換または削除します。
TRY (
try
に置き換え)CATCH (
catch
に置き換え)AND_CATCH (
catch
に置き換え)END_CATCH (削除)
THROW (
throw
に置き換え)THROW_LAST (
throw
に置き換え)例外の宣言形式が有効となるようにマクロの引数に変更を加えます。
たとえば、
CATCH(CException, e)
to
catch (CException* e)
必要に応じて例外オブジェクトを削除するように catch ブロックのコードに変更を加えます。 詳細については、「例外処理 : 例外のキャッチと削除」の記事を参照してください。
以下に示したのは、MFC 例外マクロを使用した例外処理コードの例です。 次の例のコードではマクロが使用されているため、例外 e
は自動的に削除される点に注意してください。
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e)
{
if (m_bPassExceptionsUp)
THROW_LAST();
if (m_bReturnFromThisFunction)
return;
// Not necessary to delete the exception e.
}
END_CATCH
次の例のコードでは、C++ の例外キーワードを使用しているため、例外は明示的に削除する必要があります。
try
{
// Do something to throw an exception.
AfxThrowUserException();
}
catch (CException* e)
{
if (m_bPassExceptionsUp)
throw;
if (m_bThrowDifferentException)
{
e->Delete();
throw new CMyOtherException;
}
if (m_bReturnFromThisFunction)
{
e->Delete();
return;
}
e->Delete();
}
詳細については、「例外: MFC マクロと C++ 例外の使用」を参照してください。