Search

14.7 — Function try blocks

Try and catch blocks work well enough in most cases, but there is one particular case in which they are not sufficient. Consider the following example:

In the above example, derived class B calls base class constructor A, which can throw an exception. Because the creation of object b has been placed inside a try block (in function main()), if A throws an exception, main’s try block will catch it. Consequently, this program prints:

Oops

But what if we want to catch the exception inside of B? The call to base constructor A happens via the member initialization list, before the B constructor’s body is called. There’s no way to wrap a standard try block around it.

In this situation, we have to use a slightly modified try block called a function try block.

Function try blocks

Function try blocks are designed to allow you to establish an exception handler around the body of an entire function, rather than around a block of code.

The syntax for function try blocks is a little hard to describe, so we’ll show by example:

When this program is run, it produces the output:

Construction of A failed
Oops

Let’s examine this program in more detail.

First, note the addition of the “try” keyword before the member initializer list. This indicates that everything after that point (until the end of the function) should be considered inside of the try block.

Second, note that the associated catch block is at the same level of indentation as the entire function. Any exception thrown between the try keyword and the end of the function body will be eligible to be caught here.

Finally, unlike normal catch blocks, which allow you to either resolve an exception, throw a new exception, or rethrow an existing exception, with function-level try blocks, you must throw or rethrow an exception. If you do not explicitly throw a new exception, or rethrow the current exception (using the throw keyword by itself), the exception will be implicitly rethrown up the stack.

In the program above, because we did not explicitly throw an exception from the function-level catch block, the exception was implicitly rethrown, and was caught by the catch block in main(). This is the reason why the above program prints “Oops”!

Although function level try blocks can be used with non-member functions as well, they typically aren’t because there’s rarely a case where this would be needed. They are almost exclusively used with constructors!

Don’t use function try to clean up resources

When construction of an object fails, the destructor of the class is not called. Consequently, you may be tempted to use a function try block as a way to clean up a class that had partially allocated resources before failing. However, referring to members of the failed object is considered undefined behavior since the object is “dead” before the catch block executes. This means that you can’t use function try to clean up after a class.

Function try is useful primarily for either logging failures before passing the exception up the stack, or for changing the type of exception thrown.

14.8 -- Exception dangers and downsides
Index
14.6 -- Rethrowing exceptions

8 comments to 14.7 — Function try blocks

  • Hugh Mungus

    Hey, Alex, why do function try blocks have to pass the exception to the caller? Is there any reason why it can’t be handled as soon as it’s caught?

    • Alex

      Consider the case where you have a Base and Derived class. Now let’s say Base throws an exception, and Derived catches it with a function try block. If Derived handled the exception, the caller would never know that Base had failed and might not be properly initialized. Alternatively, if you had a Base, Derived, and Last class, and Derived handled the exception, Last wouldn’t know Base had failed, and might try to access something in Base.

  • Hardik

    So, Alex, How should we prevent Function-level Try Blocks From re-throwing the same exception?
    Can you suggest any FIX?

  • susenj

    Alex, what did you mean when you said in the last line "They are almost exclusive used with derived constructors!" ?

    Thanks for the great work, btw.

    • Alex

      I meant to say, “They are almost exclusively used with derived constructors!” (I missed the -ly suffix). Meaning they’re used in that particular case only.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter