【问题标题】:Will throwing an exception in a catch block lead to two exceptions being in flight? [duplicate]在 catch 块中抛出异常会导致两个异常发生吗? [复制]
【发布时间】:2015-11-13 08:40:21
【问题描述】:

考虑以下 C++ 代码:

class MyException {};

void someFunction()
{
    try
    {
        /// ... code that may throw
    }
    catch(std::exception& e )
    {
        throw MyException();
    }
}

问题

异常 e 是在 catch 块的开头还是在 catch 块的结尾被吸收?

在第二种情况下,抛出新异常会导致两个异常在运行,这不是我想要的。我想吸收 std::exception 并开始我自己的类型。

【问题讨论】:

    标签: c++ exception exception-handling catch-block


    【解决方案1】:

    没有。这就是一个人应该这样做。 throw myException() 只能在第一个异常被捕获并因此不再“运行中”时发生。

    这种设计模式非常常见,可以将来自您的代码正在使用的另一个库的错误消息“翻译”为您的代码用户可以更好地与之关联的错误。

    或者,如果你想做的不仅仅是throw(假设你想做一些资源清理——尽管这确实应该通过 RAII 来完成,即从析构函数),那么你可以简单地重新抛出原来的异常通过

    try
    {
        // ... code that may throw
    }
    catch(...) // catches anything
    {
        // ... code that runs before rethrowing
        throw;    // rethrows the original catch
    }
    

    【讨论】:

    • @Default 在没有任何其他操作的情况下捕获然后重新抛出是没有意义的:你可以在没有 try catch 块的情况下获得相同的结果。
    • @Walter:有很多很好的理由可以抓住然后重新扔掉。没有catch + rethrow 的代码是不等价的。
    • @Cheersandhth.-Alf 你能详细说明一下吗?或者给我一个参考?
    • 不仅是为了清理资源——另一个说明你为什么想要throw; 的例子是记录异常。
    • @Walter:例如,使用try 中的catch(...) 块代码或从该代码调用,可以保证在堆栈展开期间调用本地对象析构函数,因为有 是 catch。我想这是最根本的技术差异。但也有更高层次更实际的区别,比如下断点的能力。
    【解决方案2】:

    只需 throw; 语句在 catch 块中就足以在更高的上下文中重新抛出相同的异常。 它再次抛出相同的异常。不会产生新的异常。所以没有战斗:)

    如果你想捕获 A 类型的异常,然后抛出 B 类型的异常,那么你的做法是绝对正确的。 在这种情况下,旧异常(类型 A)被捕获(吸收),只有新异常(类型 B)被抛出到更高的上下文。所以,再次没有战斗:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-21
      • 2011-03-18
      • 1970-01-01
      • 2016-01-06
      • 2023-04-01
      相关资源
      最近更新 更多