Catching exceptions

The syntax to declare a block of code as being able to catch an exception being thrown in another block of code is not as straightforward as most texts lead you to believe. The main syntax is, of course, pretty simple:

// catch all exceptions
try {
  // code which throws an exception 
} catch (...) {
  // code which catches any exception 
}

// catch only a given type of exceptions
try {
  // code which throws an exception 
} catch (const Excp &e) {
  // code which catches only exceptions of type const Excp 
}

The catch handler catches either all exceptions if the exception specification is ... or only a given exception type as specified by the exception specification. A handler matches an exception type if both underlying types are intuitively compatible in a way similar to that of a function call and its arguments. [2] The code in the catch handler can then access a copy of the original exception object. If this catch handler does not decide to progate the original exception with an empty throw; statement, it can throw another new exception (the original exception object is often copied into the new exception object to keep information about where the exception comes from) or not throw anything in which case stack unwinding stops and resumes after the catch block.

Catching exceptions can become interesting when you look at the more subtle syntax for the so-called function-try:

C::C(int ii, double id)
  try
    : i(f(ii)), d(id) // initializer list.
{
  //  constructor function body
}
  catch (...)
{
  //  handles exceptions thrown from the ctor-initializer
  //  and from the constructor function body
}

This function-try is used to catch exceptions thrown either during the initialization of the members of an object of during the execution of the constructor body of this object. In the sample code above, the catch block will be executed if an exception is thrown during the construction of the initializer list or during the excution of the function body. The exception is automatically rethrown when control reaches the end of the catch block. This means that it is impossible to actually catch exceptions and stop their propagation in a function-try-block which kind of defeats the whole purpose of a catch block! [3]

Robert Schmidt discusses the details of this rather surprising behavior in Part 14 of his C++ exceptions articles (se e the section called “References”).



[2] The C++ standard defines this in section 15.3, paragraph 3.

[3] see section 15.3, paragraph 10 to 16, C++ standard.