I am refactoring some legacy C++ MFC code and have come across this construct:
TRY
{
// do some stuff
}
CATCH
{
// do some other stuff
}
END_CATCH
To me this seems quite unusual, and I am trying to understand what is the benefit of using TRY/CATCH
in favor of try/catch
.
I see that TRY
creates an instance of AFX_EXCEPTION_LINK
and I don't quite understand the purpose of this. My googling skill failed miserably.
Without a try catch, you run the risk of encountering unhandled exceptions. Try catch statements aren't free in that they come with performance overhead. Like any language feature, try catches can be overused.
The try statement allows you to define a block of code to be tested for errors while it is being executed. The catch statement allows you to define a block of code to be executed, if an error occurs in the try block.
Throw, and Try...Catch... The try statement defines a code block to run (to try). The catch statement defines a code block to handle any error. The finally statement defines a code block to run regardless of the result. The throw statement defines a custom error.
In simple words, in case of checked exception the compiler will force you to put a try catch or throws. In case of unchecked exception, compiler doesnt mind if you dont put try catches and throws. It is almost always a bad practice to put try catch in cases of unchecked exception like in the code.
MFC (and its exception processing macros) predate the C++98 language specification. The macros attempt to abstract common boilerplate code away, when using exceptions in MFC. The boilerplate code is necessary due to the design decision, that exceptions in MFC are dynamically allocated1, and need to be manually disposed.
The steps required to replace the MFC exception handling macros with C++ exception handling are documented under Exceptions: Converting from MFC Exception Macros:
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
, andTHROW_LAST
.Replace or delete all occurrences of the following macros:
TRY
(Replace it withtry
)CATCH
(Replace it withcatch
)AND_CATCH
(Replace it withcatch
)END_CATCH
(Delete it)THROW
(Replace it withthrow
)THROW_LAST
(Replace it withthrow
)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(); }
The conversion is almost mechanical, as long as you remember to manually delete MFC exceptions by invoking CException::Delete.
1This is in contrast to the C++ exception handling convention today: Throw by value, catch by (const) reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With