嵌套捕获运算符

时间:2013-12-02 14:05:44

标签: c++ exception

我需要捕获可能由try ... catch构造中的代码抛出的异常,并根据异常类型执行某些操作。但是如果抛出任何异常,我也想做一些代码。 我这样做了:

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

我的代码有效,但我想知道标准是否说明了什么。 也许有更好的方法吗?

UPD :对于评论的慢回答感到抱歉。简单,英语是我的第二语言。

UPD :我认为AdelNick的代码或Steve Jessop的第二个代码或DavidRodríguez的第二个代码 - dribeas适合我。

4 个答案:

答案 0 :(得分:3)

您的方法很糟糕,因为如果// here is code that are executed if any exception are thrownexc1分支都没有捕获到异常,则不会执行exc2部分。您的代码是以下内容的等效版本:

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

C++语言不支持finally块,如果这就是你所追求的。这是因为对象的析构函数负责释放资源,而不是finally块。以下是该主题的Stroustrup's explanation

答案 1 :(得分:3)

你应该写:

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

如果您希望特定代码作为所有三种情况的一部分执行,那么您有两个选择:在所有三个地方调用它,或者执行以下操作:

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
}

答案 2 :(得分:1)

我会将代码顺序更改为:

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
}

如果抛出任何其他类型的异常(不仅是 exc1 exc2 ),它也能正常工作。此外,如果所有异常的共同代码是资源释放,请考虑使用RAII原则。)

答案 3 :(得分:1)

看一下评论似乎你可能会期待一些不会发生的事情,这已经在其他答案中讨论过了。但这可能是我们方面的误解。如果try中的代码只能抛出exc1exc2中的一个,那么是的,它会按预期执行。

从评论更新中,似乎意图处理任何异常,包括既不是exc1也不是exc2的异常。为此,代码将不会执行预期的操作,exc3将在嵌套的try之外传播。只需展平两个级别,最后添加catch (...)


从这里开始,答案基于对该问题的错误假设。

标准支持重新抛出模式,并且在不同上下文中异常的处理相同以避免代码重复的情况下通常使用:

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();
   }
}

如果处理异常的代码不会集中用于不同的函数,那么该模式可能会使代码比您需要的更复杂。您可以考虑使用额外的控制变量进行单个try / catch:

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