我一直相信,如果一个方法可以抛出异常,那么不使用有意义的try块来保护这个调用就是鲁莽的。
我刚刚发布了‘你应该总是包装调用,可以抛出try, catch块。,结果被告知这是一个“非常糟糕的建议”——我想知道为什么。
我一直相信,如果一个方法可以抛出异常,那么不使用有意义的try块来保护这个调用就是鲁莽的。
我刚刚发布了‘你应该总是包装调用,可以抛出try, catch块。,结果被告知这是一个“非常糟糕的建议”——我想知道为什么。
当前回答
您不需要在try-catch中掩盖代码的每一部分。try-catch块的主要用途是错误处理和获取程序中的错误/异常。try-catch -的用法
您可以在想要处理异常的地方使用此块,或者简单地说编写的代码块可能抛出异常。 如果你想在对象使用后立即释放它们,你可以使用try-catch块。
其他回答
您不需要在try-catch中掩盖代码的每一部分。try-catch块的主要用途是错误处理和获取程序中的错误/异常。try-catch -的用法
您可以在想要处理异常的地方使用此块,或者简单地说编写的代码块可能抛出异常。 如果你想在对象使用后立即释放它们,你可以使用try-catch块。
You don't need to cover every block with try-catches because a try-catch can still catch unhandled exceptions thrown in functions further down the call stack. So rather than have every function have a try-catch, you can have one at the top level logic of your application. For example, there might be a SaveDocument() top-level routine, which calls many methods which call other methods etc. These sub-methods don't need their own try-catches, because if they throw, it's still caught by SaveDocument()'s catch.
这样做很好,有三个原因:它很方便,因为只有一个地方可以报告错误:SaveDocument()捕获块。没有必要在所有子方法中重复这一点,而且这正是您想要的:在一个单一的位置为用户提供关于出错的有用诊断。
第二,每当抛出异常时,保存将被取消。对于每个尝试捕获子方法,如果抛出异常,则进入该方法的捕获块,执行离开函数,并通过SaveDocument()继续进行。如果事情已经出了问题,你可能会想就此打住。
第三,所有子方法都可以假设每次调用都成功。如果调用失败,执行将跳转到catch块,后续代码永远不会执行。这可以使您的代码更加清晰。例如,下面是错误代码:
int ret = SaveFirstSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
ret = SaveSecondSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
ret = SaveThirdSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
下面是如何编写例外情况:
// these throw if failed, caught in SaveDocument's catch
SaveFirstSection();
SaveSecondSection();
SaveThirdSection();
现在发生了什么更加清楚了。
注意,以其他方式编写异常安全代码可能更加棘手:如果抛出异常,您不希望泄漏任何内存。确保你了解RAII、STL容器、智能指针和其他在析构函数中释放资源的对象,因为对象总是在异常之前被析构。
正如在其他回答中所述,只有在可以对异常进行某种合理的错误处理时才应该捕获异常。
例如,在生成您的问题的问题中,提问者询问忽略从整数到字符串的lexical_cast异常是否安全。这样的阵容永远不会失败。如果它失败了,说明程序中出现了严重的错误。在这种情况下,你能做些什么来恢复呢?最好的方法可能是让程序死亡,因为它处于不可信任的状态。因此,不处理异常可能是最安全的做法。
除了上面的建议,我个人使用尝试+抓+扔的方法;原因如下:
At boundary of different coder, I use try + catch + throw in the code written by myself, before the exception being thrown to the caller which is written by others, this gives me a chance to know some error condition occured in my code, and this place is much closer to the code which initially throw the exception, the closer, the easier to find the reason. At the boundary of modules, although different module may be written my same person. Learning + Debug purpose, in this case I use catch(...) in C++ and catch(Exception ex) in C#, for C++, the standard library does not throw too many exception, so this case is rare in C++. But common place in C#, C# has a huge library and an mature exception hierarchy, the C# library code throw tons of exception, in theory I(and you) should know every exceptions from the function you called, and know the reason/case why these exception being thrown, and know how to handle them(pass by or catch and handle it in-place)gracefully. Unfortunately in reality it's very hard to know everything about the potential exceptions before I write one line of code. So I catch all and let my code speak aloud by logging(in product environment)/assert dialog(in development environment) when any exception really occurs. By this way I add exception handling code progressively. I know it conflit with good advice but in reality it works for me and I don't know any better way for this problem.
如果总是在可能抛出异常的方法的调用者中立即处理异常,那么异常就变得毫无用处,最好使用错误代码。
异常的全部意义在于,不需要在调用链中的每个方法中处理它们。