我是否仍然可以在catch块中调用的函数中重新抛出异常?

X''*_*X'' 2 c++ try-catch rethrow

我在遗留代码库中有以下结构:

try{
...
}
catch(Type1&){
...
}
catch(Type2&){
...
}
...
Run Code Online (Sandbox Code Playgroud)

通过复制粘贴开发,相同的catch块随处可见.现在,我会编写一个这样的函数:

void catchErrors(){
  try{
    throw;
  }
  catch(Type1&){
    ...
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

并将其放入代码中,如下所示:

try{
  ...
}
catch(...){
  catchErrors();
}
Run Code Online (Sandbox Code Playgroud)

这是一个有效的重构,导致相同的功能吗?
(你对重构有什么更好的建议吗?)

Lig*_*ica 5

是的,这是有效的.

[C++14: 15.1/8]:没有操作数的throw-expression重新抛出当前处理的异常(15.3).使用现有异常对象重新激活该异常; 没有创建新的异常对象.该例外情况不再被视为被捕; 因此,价值std::uncaught_exception()将再次成真.

[示例:由于异常而无法完全处理异常而必须执行的代码可以这样写:

try {
  // ...
} catch (...) { // catch all exceptions
  // respond (partially) to exception
  throw; // pass the exception to some
  // other handler
}
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

[C++14: 15.1/9]:如果当前没有处理异常,则执行不带操作数调用的throw-expression std::terminate()(15.5.1).

尽管throw-expression已被移入其自己的函数中,但在执行期间仍然会处理异常,因此它仍然有效:

#include <iostream>

void bar()
{
    try {
        throw;
    }
    catch (int x) {
        std::cerr << "Damn " << x << "!\n";
    }
}

void foo()
{
    try {
        throw 42;
    }
    catch (...) {
        bar();
    }
}

int main()
{
    foo();
}

// Output: Damn 42!
Run Code Online (Sandbox Code Playgroud)

(现场演示)