Joh*_*ang 6 c++ exception try-catch throw
我的意思是,我知道关于throw的所有语言规则,尝试{} catch {},但我不确定我是否在现实世界中正确使用它们.请参阅以下示例:
我们有大量的科学代码可以完成各种图像处理工作,最近我们决定对其进行修改,使其更加强大.经常使用的一个例程是void rotate_in_place(float*image,image_size sz) ;
为了使其更加健壮,我们在代码的开头添加了一些健全性检查:
void rotate_in_place(float* image, image_size sz) {
// rotate_in_place does not support non-square image;
if (sz.nx != sz.ny) throw NonSquareImageError;
// rotate_in_place does not support image too small or too large
if (sz.nx <= 2 || sz.nx > 1024) throw WrongImageSizeError;
// Real rode here
.....
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是rotate_in_place()在1000多个地方使用,我应该用try {} catch {}包装每次调用rotate_in_place(),这对我来说会让代码难以置信地膨胀.另一种可能性是不包装任何try {} catch {}并让程序退出,但这与仅使用有什么不同
if (sz.nx != sz.ny) {
cerr << "Error: non-squared image error!\n";
exit(0);
}
Run Code Online (Sandbox Code Playgroud)
简而言之,我不太确定使用throw,try,catch,任何好建议的真正好处?
处理错误的每个站点都需要try
- catch
阻止.这一切都取决于你的设计,但我怀疑你需要在每个rotate_in_place
呼叫站点处理错误,你可能在大多数时间都不会向上传播.
打印错误和使用exit
是不好的有三个原因:
exit
没有处理(除非在错误绝对严重时完成,但你的功能无法知道 - 调用者可能有办法恢复).rotate_in_place
不是rotate_in_place_and_print_errors_and_kill_the_program_if_something_is_wrong
) - 这会损害可重用性.例外的一般规则是,"即时呼叫站点是否关心这里发生了什么?" 如果呼叫站点确实关心,那么返回状态代码可能是有意义的.否则,投掷更有意义.
以这种方式考虑 - 当然,你的rotate in place方法有几个无效的参数类型,在这种情况下你应该抛出std::invalid_argument
.例如,rotate_in_place
想要处理或知道如何处理图像不是正方形的情况的调用者不太可能,因此可能更好地表示为异常.
另一种可能性是不包装任何try {} catch {}并让程序退出,但这与仅使用有什么不同
Run Code Online (Sandbox Code Playgroud)if (sz.nx != sz.ny) { cerr << "Error: non-squared image error!\n"; exit(0); }
这是不同的,因为如果有人后来想要将您的功能放入GUI应用程序中,则他们不必根据错误终止程序.他们可以将该异常转化为适合用户或类似的东西.
它现在对你也有好处 - 也就是你不必<iostream>
简单地写入错误写入翻译单元.
我通常使用这样的模式:
int realEntryPoint()
{
//Program goes here
}
int main()
{
//Allow the debugger to get the exception if this is a debug binary
#ifdef NDEBUG
try
#endif
{
return realEntryPoint();
}
#ifdef NDEBUG
catch (std::exception& ex)
{
std::cerr << "An exception was thrown: " << ex.what() << std::endl;
}
#endif
}
Run Code Online (Sandbox Code Playgroud)