Dmitry
Dmitry

Reputation: 47

Nested catch operators

I need catch exceptions that are maybe thrown by code in try...catch construction, and do something depending on exception type. But also I want do some code if any exception are thrown. I did so:

try
{
    // code
}
catch (...)
{
    try
    {
        throw;
    }
    catch (exc1)
    {
        // handling
    }
    catch (exc2)
    {
        // handling
    }
    // here is code that are executed if any exception are thrown
}

My code works, but I want to know whether the Standard says anything about it. Maybe is there any better method?

UPD: Sorry for the slow answers to comments. Simple, English is a second language for me.

UPD: I think that code from AdelNick or second code from Steve Jessop or second code from David Rodríguez - dribeas are right for me.

Upvotes: 1

Views: 107

Answers (4)

Looking at the comments it seems that you may be expecting something that won't happen, and that has already been discussed in other answers. But it could be a misunderstanding on our side. If the code inside the try can only throw one of exc1 or exc2 then yes, it will do what you expect.

From the comment update, it seems that the intention was to handle any exception, including those that are neither exc1 nor exc2. For that purpose, the code won't do what is expected and exc3 will propagate outside of the nested trys. Just flatten the two levels and add a catch (...) at the end.


From here on the answer was based on a false assumption about the question.

The pattern of rethrowing is supported by the standard and used commonly in situations where the handling of the exceptions in different contexts is the same to avoid code duplication:

void processException() {
   // implement exception handling in all contexts
   try {
     throw;
   } catch (exceptionType1 const & ex1) {
   } catch (exceptionType2 const & ex2) {
// } catch (...) {
   }
}
void f() {
   try {
      something();
   } catch (...) {
      processException();
   }
}
void g() {
   try {
      anotherThing();
   } catch (...) {
      processException();
   }
}

If the code to handle the exceptions is not going to be centralized for different functions, that pattern may complicate the code more than you need. You could consider a single try/catch with an extra control variable:

bool success = false;
try {
   doSomething();
   success = true;
} catch (exception1 const & ex1) {
...
} catch (exception2 const & ex2) {
...
// } catch (...) {
}
if (!success) {
   // common code to all exceptions
}

Upvotes: 1

AdelNick
AdelNick

Reputation: 993

I would change the code order as following:

try
{
    try
    {
      // code
    }
    catch (exc1)
    {
        // handling
        throw; // edited. was: throw exc1;
    }
    catch (exc2)
    {
        // handling
        throw; // edited. was: throw exc2;
    }
} 
catch(...)
{
    // here is code that are executed if any exception are thrown
}

as it works if any other type of exception is thrown (not only exc1 or exc2). Also if the code common for all exceptions is the resource releasing, consider using RAII principle instead).

Upvotes: 1

Steve Jessop
Steve Jessop

Reputation: 279245

You should write:

try
{
    // code
}
catch (exc1)
{
    // handling
}
catch (exc2)
{
    // handling
}
catch (...) 
{
    // here is code that are executed if any *other* exception are thrown
}

If you want particular code to be executed as part of all three cases then you have two options: call it in all three places, or do something like this:

bool threw = true;
try
{
    // code
    threw = false;
}
catch (exc1)
{
    // handling
}
catch (exc2)
{
    // handling
}
catch (...) {
}
if (threw) {
    // here is code that are executed if any exception are thrown
}

Upvotes: 3

mcserep
mcserep

Reputation: 3299

Your approach is bad, because the // here is code that are executed if any exception are thrown part won't be executed if neither of exc1 or exc2 branch catch the exception. Your code is an equivalent version of the following:

try
{
    // code
}
catch (exc1)
{
    // handling
}
catch (exc2)
{
    // handling
}
// here is code that are executed if any exception are thrown

The C++ language does not support a finally block, if that's what you're after. That is because an object's destructor is responsible for freeing resources, not a finally block. Here is Stroustrup's explanation of the topic.

Upvotes: 3

Related Questions