C++核心准则E.30:不要使用抛异常声明
不要使用抛异常声明
月季
E.30: Don't use exception specifications
E.20:不要使用抛异常声明
Reason(原因)
Exception specifications make error handling brittle, impose a run-time cost, and have been removed from the C++ standard.
抛异常声明让错误处理更脆弱,强制产生运行时成本,已经从C++标准中被移除了。
Example(示例)
int use(int arg)
throw(X, Y)
{
// ...
auto x = f(arg);
// ...
}
If f() throws an exception different from X and Y the unexpected handler is invoked, which by default terminates. That's OK, but say that we have checked that this cannot happen and f is changed to throw a new exception Z, we now have a crash on our hands unless we change use() (and re-test everything). The snag is that f() may be in a library we do not control and the new exception is not anything that use() can do anything about or is in any way interested in. We can change use() to pass Z through, but now use()'s callers probably needs to be modified. This quickly becomes unmanageable. Alternatively, we can add a try-catch to use() to map Z into an acceptable exception. This too, quickly becomes unmanageable. Note that changes to the set of exceptions often happens at the lowest level of a system (e.g., because of changes to a network library or some middleware), so changes "bubble up" through long call chains. In a large code base, this could mean that nobody could update to a new version of a library until the last user was modified. If use() is part of a library, it may not be possible to update it because a change could affect unknown clients.
如果f()抛出了不同于X和Y的异常,就会激活意外的错误处理,而这个处理的默认动作就是终止程序。那样还好,假设我们已经检查过了,这种事情不会发生,这时如果f被修改为抛出一个新异常Z,系统马上就会发生崩溃,除非我们修改use()(并且重新进行完整测试)。麻烦在于f()可能处于某个我们无法控制的功能库中,而且对于新异常use()也没有什么可做的,或者根本就不感兴趣。我可以修改use()将Z传出,但是接下来user()的调用者可能需要跟着修改。情况很快就会失控。或者我们可以为use()增加try-catch结构将Z映射到一个可以接受的异常。情况很快会再次失控。注意成组修改异常经常发生在系统的底层(例如由于网络库或某个中间件发生变化),因此变更会像气泡一样向上传递至整个调用链。在大规模代码中,这可能意味着没有人可以将库更新到新版本,直到最后的调用者发生变更。如果use()是库的一部分,它可能无法更新,因为这种变更不知道会影响谁。
The policy of letting exceptions propagate until they reach a function that potentially can handle it has proven itself over the years.
让异常传播直至一个有可能处理它的函数,这样的原则已经证明自己很多年了。
Note(注意)
No. This would not be any better had exception specifications been statically enforced. For example, see Stroustrup94.
没有。坚持推进使用抛异常声明一点好处也没有。参见
Stroustrup. The Design and Evolution of C++ (Addison-Wesley, 1994).
Note(注意)
If no exception may be thrown, use noexcept or its equivalent throw().
如果不会抛出任何异常,使用noexcept或者和它等价的throw()
Enforcement(实施建议)
Flag every exception specification.
标记所有的抛出异常声明。
原文链接
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e30-dont-use-exception-specifications
新书介绍
以下是本人3月份出版的新书,拜托多多关注!
本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。
对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。
觉得本文有帮助?请分享给更多人。
关注微信公众号【面向对象思考】轻松学习每一天!
面向对象开发,面向对象思考!