Exceptions: Converting from MFC Exception Macros
This is an advanced topic.
This article explains how to convert existing code written with Microsoft Foundation Class macros — TRY, CATCH, THROW, and so on — to use the C++ exception-handling keywords try
, catch
, and throw
. Topics include:
Advantages of Converting
You probably do not need to convert existing code, although you should be aware of differences between the macro implementations in MFC version 3.0 and the implementations in earlier versions. These differences and subsequent changes in code behavior are discussed in Exceptions: Changes to Exception Macros in Version 3.0.
The principal advantages of converting are:
Code that uses the C++ exception-handling keywords compiles to a slightly smaller .EXE or .DLL.
The C++ exception-handling keywords are more versatile: They can handle exceptions of any data type that can be copied (
int
,float
,char
, and so on), whereas the macros handle exceptions only of classCException
and classes derived from it.
The major difference between the macros and the keywords is that code using the macros "automatically" deletes a caught exception when the exception goes out of scope. Code using the keywords does not, so you must explicitly delete a caught exception. For more information, see the article Exceptions: Catching and Deleting Exceptions.
Another difference is syntax. The syntax for macros and keywords differs in three respects:
Macro arguments and exception declarations:
A CATCH macro invocation has the following syntax:
CATCH( exception_class, exception_object_pointer_name )
Notice the comma between the class name and the object pointer name.
The exception declaration for the
catch
keyword uses this syntax:catch( exception_type exception_name )
This exception declaration statement indicates the type of exception the catch block handles.
Delimitation of catch blocks:
With the macros, the CATCH macro (with its arguments) begins the first catch block; the AND_CATCH macro begins subsequent catch blocks, and the END_CATCH macro terminates the sequence of catch blocks.
With the keywords, the
catch
keyword (with its exception declaration) begins each catch block. There is no counterpart to the END_CATCH macro; the catch block ends with its closing brace.The throw expression:
The macros use THROW_LAST to re-throw the current exception. The
throw
keyword, with no argument, has the same effect.
Doing the Conversion
To convert code using macros to use the C++ exception-handling keywords
Locate all occurrences of the MFC macros TRY, CATCH, AND_CATCH, END_CATCH, THROW, and THROW_LAST.
Replace or delete all occurrences of the following macros:
TRY (Replace it with
try
)CATCH (Replace it with
catch
)AND_CATCH (Replace it with
catch
)END_CATCH (Delete it)
THROW (Replace it with
throw
)THROW_LAST (Replace it with
throw
)Modify the macro arguments so that they form valid exception declarations.
For example, change
CATCH(CException, e)
to
catch (CException* e)
Modify the code in the catch blocks so that it deletes exception objects as necessary. For more information, see the article Exceptions: Catching and Deleting Exceptions.
Here is an example of exception-handling code using MFC exception macros. Note that because the code in the following example uses the macros, the exception e
is deleted automatically:
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
The code in the next example uses the C++ exception keywords, so the exception must be explicitly deleted:
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();
}
For more information, see Exceptions: Using MFC Macros and C++ Exceptions.