在异常处理程序中使用'goto'是不好的风格吗?
Is using 'goto' in exception handlers bad style?
自从我开始编程以来,我被教导在可以避免的情况下永远不要使用"goto"。I、 然而,我遇到了一个案例,我认为goto是保持代码干净的最简单方法。
我的代码看起来像下面的例子:
// code within a for-loop
// ...
// ...
try{
if(!ifstream.open())
throw special_exception;
A_EXCEPTION_HANDLED:
//...
//...
}
catch(special_exception ex)
{
// trying to fix the error here
if(error_is_fixed)
goto A_EXCEPTION_HANDLED;
// else clean up and show error message
};
这个例子在一个嵌套循环中,我需要确保抛出之后的代码执行正确,所以我必须写大量的开销来再次启动迭代,在迭代中抛出了异常。这种情况会被认为是对goto的合理使用,还是像跳出循环等一样糟糕?
我认为根据您的描述,代码可以这样重写:
for ( /* usual stuff */ )
try{
if(!ifstream.open())
throw special_exception;
} catch (const special_exception&) {
if (/* "can't handle the truth!" */) {
// clean up & show error message
break;
}
}
// OK, continue
}
在异常后重试的概念并非闻所未闻(例如:Common Lisp将类似的东西作为语言的一部分来实现)。
然而,你真的需要一个例外吗?如果你(与库相反)抛出异常,并且只有一个地方抛出它(正如你的例子所示),你就不能简单地写这样的东西吗?
if(!ifstream.open()) {
// trying to fix the error here
if(!error_is_fixed) {
throw really_unrecoverable();
}
// else let it continue normally
}
如果这种逻辑重复得太频繁,我可以看到异常的正当性,并使用goto重试算法。但是,如果这种情况只发生一两次,我会以内联方式编写恢复代码(也许使用辅助函数)。
使用goto
实现循环不是对goto
的合理使用。
要在C++中实现循环,请使用循环构造。
关于您具体案例的细节,请务必提供。
在您给出的示例中,我认为使用goto遍历两个块确实是一种糟糕的风格。
现在"goto"的使用会产生各种不受欢迎的歇斯底里,但在这种情况下,它糟糕风格的原因非常清楚:
代码的读者可能会合理地认为,一旦调用了异常处理程序,就会发生一些非常糟糕的事情,阻止当前代码上下文继续运行。如果预期ifstream存在,但实际不存在,则这是一种例外情况,并且有必要进行例外处理。然而,如果打开流的尝试只是一个测试,可以合理地预期会失败,那么这并不是一件例外的事情。在这种情况下,根本不要使用异常。在这种情况下,表达意图的更好方式可能是这样的:
for(/* usual stuff */)
while (!ifstream.open()) {
if (!attemptRemedialAction()) {
throw really_bad_thing_happened_exception;
}
}
// do things with ifstream,
// including goto statements if they express your intent elegantly
}
// allow the outer context or the caller to deal with the exceptional case of non-recovery
风格正是它听起来的样子。有些人喜欢一个,另一些人喜欢另一个。作为一名开发人员,你将与许多人一起工作,并且必须处理他们不同的风格。
真正重要的不是宣扬一种风格而不是另一种风格,而是在项目中保持风格的一致性。如果这个项目使用goto
,那么坚持使用它,并相应地编写您的部分。因为其他开发人员会期待跳跃,并会寻找它们。
(顺便说一句,有些系统在任何给定的时间都只允许存在一个异常,例如Symbian和其他EPOC衍生物,所以我们在这里看到的可能是必要的,而不是风格)
- 与异常处理程序中的操作员<<不匹配
- 数组 C++ 上的异常处理程序
- 视觉 std::矢量无异常:警告 C4530:使用了C++异常处理程序,但未启用展开语义.指定 /EHsc
- 奇怪的消息 (_Base_bitset::_M_do_to_ulong) 从溢出异常处理程序中打印出来
- C++ 中未处理的异常处理程序
- 如何在 Windows 异常处理程序中设置 MMX 寄存器以模拟不受支持的 3DNow! 说明
- G++ 自定义异常处理程序
- 内部异常处理程序,MessageBox()成功返回IDOK,但从未显示
- 如何从将触发脚本异常处理程序的C++引发异常
- 将 INT3 中断保留给视觉工作室上的应用程序异常处理程序
- 如何在气泡排序中为字符串和双精度实现异常处理程序
- 从硬件异常处理程序引发C++异常.为什么 -fnon-call-exception 没有按预期运行
- 我应该如何编写国际化的异常处理程序
- 使用try-Catch异常处理程序和if-else条件检查之间的区别
- 异常处理程序
- 我可以从Qt中的异常处理程序中发出信号吗
- c++异常处理程序中嵌套的try..catch
- 结构化异常处理程序(SEH)不会捕获堆损坏
- MSVC++6.0:C1509“函数中的异常处理程序状态太多”
- 在异常处理程序中使用'goto'是不好的风格吗?