在C++中重用异常处理代码
Reusing exception handling code in C++
>我有两个函数,带有重复的异常处理,其唯一目的是显示错误消息:
void func1() noexcept {
try {
do_task();
do_another_task();
} catch (const std::out_of_range& e) {
show_msg("Out of range error", e.what());
} catch (const std::logic_error& e) {
show_msg("Logic error", e.what());
} catch (const std::system_error& e) {
show_msg("System error", e.what());
} catch (const std::runtime_error& e) {
show_msg("Runtime error", e.what());
} catch (const std::exception& e) {
show_msg("Generic error", e.what());
}
}
void func2() noexcept {
try {
do_something();
do_something_else();
do_even_more();
} catch (const std::out_of_range& e) {
show_msg("Out of range error", e.what());
} catch (const std::logic_error& e) {
show_msg("Logic error", e.what());
} catch (const std::system_error& e) {
show_msg("System error", e.what());
} catch (const std::runtime_error& e) {
show_msg("Runtime error", e.what());
} catch (const std::exception& e) {
show_msg("Generic error", e.what());
}
}
我可以只处理std::exception
并显示单个通用消息,但我想更具体,这就是我捕获所有可能的异常的原因。
我想重用此异常处理代码。我想到了这个:
void run_treated(std::function<void()> func) noexcept {
try {
func();
} catch // ... all the catches go here
}
void func1() noexcept {
run_treated([]()->void {
do_task();
do_another_task();
});
}
void func2() noexcept {
do_something();
do_something_else();
do_even_more();
}
- 这是一个好方法吗?
- 如果是这样,
run_treated
将被召唤很多。我应该关注性能吗? - 还有其他方法吗?
可以选择使用 Lippincott 函数来集中异常处理逻辑。考虑一下:
void Lippincott () noexcept {
try {
throw;
} catch (const std::out_of_range& e) {
show_msg("Out of range error", e.what());
} catch (const std::logic_error& e) {
show_msg("Logic error", e.what());
} catch (const std::system_error& e) {
show_msg("System error", e.what());
} catch (const std::runtime_error& e) {
show_msg("Runtime error", e.what());
} catch (const std::exception& e) {
show_msg("Generic error", e.what());
}
}
void func1() noexcept {
try {
do_task();
do_another_task();
} catch (...) {
Lippincott();
}
}
void func2() noexcept {
try {
do_something();
do_something_else();
do_even_more();
} catch (...) {
Lippincott();
}
}
它是如何工作的?当您在func1
或func2
中输入处理程序时,将处理"当前异常"。Lippincott
的身体开始新的尝试。抓住块并重新投掷它。然后,它会捕获适当的异常,并以集中的方式相应地处理它们。
您还应该注意,您的异常处理逻辑并不是真正noexcept
。理论上可能存在您的列表未涵盖的例外情况。在这种情况下,有几个地方可以调用std::terminate
,具体取决于您如何标记事物noexcept
这是一个好方法吗?
是的。它可以防止代码重复,并允许您通过传入 lambda 轻松自定义行为。
如果是这样,
run_treated
将被称为很多。我应该关注性能吗?
是的。std::function
不是零成本抽象。您应该使用模板参数来传递 lambda,而无需类型擦除。
template <typename F>
void run_treated(F&& func) noexcept {
try {
std::forward<F>(func)();
} catch // ... all the catches go here
}
我在本文中讨论并测试了将函数传递给其他函数的各种技术:">将函数传递给函数"。
如果您不想使用模板来传递func
,则可以使用类似function_ref
(建议用于标准化 P0792)的内容。此处提供实现:function_ref.cpp
。
不相关的评论:
那些无条件的
noexcept
说明符看起来很可疑。您真的能保证没有异常会逃脱这些功能吗?[]()->void {}
相当于[]{}
。
相关文章:
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Firebase C++VS2018 SDL2-在Firebase::app::create(..)上执行异常处理
- 使用 stoi 功能进行异常处理
- 子系统中的异常处理:本机
- 与异常处理程序中的操作员<<不匹配
- 数组 C++ 上的异常处理程序
- 无法看到引发异常的代码行
- 使用双LL在C++中实现Stack失败,出现异常"EXC_BAD_ACCESS(代码=2,地址=0x7fff5
- 异常处理:如果用户输入不是三个特定字符之一
- C++ 异常处理错误输出
- 在C++中重用异常处理代码
- 具有两个类似catch部分的代码的异常处理行为
- 是否可以对构造函数抛出异常的对象进行异常处理,该对象的异常处理接近其基于堆栈的代码创建
- 在异常处理中,对性能的影响会随着 try 部分中的代码量而增长
- 以下哪个异常处理代码段有效,原因
- 使用不支持异常处理的代码(C++/LLVM)进行链接
- 我应该在现有的代码库中添加异常处理吗?
- C代码中的C++异常处理
- 使用异常处理库的(可能更改的)错误代码