有没有一个普遍接受的成语,指示C ++代码可以抛出异常?
使用C ++代码时,遇到问题,意外的是调用者抛出异常。阅读您正在使用的模块的每一行,看看它是否引发异常并不总是可行或实际的,如果是这样,那么是什么类型的异常。
I have seen problems when using C++ code that, unexpectedly to the caller, throws an exception. It's not always possible or practical to read every line of a module that you are using to see if it throws exceptions and if so, what type of exception.
是否已经建立成语或处理这个问题的最佳实践?
Are there established idioms or "best practices" that exist for dealing with this problem?
我想到了以下几点:
(1)在我们的doxygen文档中,我们可以在预期会抛出异常的每个函数中添加一个注释,它的类型是。
Pluses:Simple。
Minuses:取决于用户错误。
(1) In our doxygen documentation, we could add a comment in every function that is expected to throw an exception and it's type(s).
Pluses: Simple.
Minuses: Subject to user error.
(2)为安全起见,我们可以有一个应用范围的try / catch(...)。
Pluses:我们不会任何更多的未捕获的例外。
Minuses:异常被捕获远离投掷。很难弄清楚该做什么或出了什么问题。
(2) We could have an app-wide try/catch(...) for safety.
Pluses: We won't have any more uncaught exceptions.
Minuses: The exception is caught far away from the throw. It's hard to figure out what to do or what went wrong.
(3)使用异常规格
Pluses:这是语言认可的方式处理这个问题。
Minuses:重构需要的问题库才能生效。编译时不执行,所以违规行为会变成运行时问题,这正是我想避免的问题!
(3) Use Exception Specifications
Pluses: This is the language-sanctioned way of dealing with this problem.
Minuses: Refactoring of problem libraries needed for this to be effective. Not enforced at compile-time, so violations turn into run-time problems, which is what I'm trying to avoid!
这些方法的任何经验,或任何额外的方法我不知道?
Any experiences with these methods, or any additional methods that I'm unaware of?
解决问题的惯用方式不是表示您的代码可以抛出异常,但是在对象中实现异常安全。该标准定义了对象应该实现的几个异常保证:
The idiomatic way to solve the problem is not to indicate that your code can throw exceptions, but to implement exception safety in your objects. The standard defines several exception guarantees objects should implement:
- 无抛出保证:该函数将永远不会抛出例外
- 强大的异常安全保证:如果抛出异常,对象将处于初始状态。
- 基本异常安全保证:如果抛出异常,该对象将处于有效状态。
- No-throw guarantee: The function will never throw an exception
- Strong exception safety guarantee: If an exception is thrown, the object will be left in its initial state.
- Basic exception safety guarantee: If an exception is thrown, the object be left in a valid state.
当然,标准文档的异常安全级别每个标准库类。
And of course, the standard documents the level of exception safety for every standard library class.
这是处理C ++中异常的方法。而不是标记哪个代码可以或不能抛出异常,使用RAII确保您的对象被清理,并考虑在您的RAII对象中实施适当级别的异常安全性,以便在没有特殊处理的情况下能够生存抛出异常。
That's really the way to deal with exceptions in C++. Rather than marking which code can or can not throw exceptions, use RAII to ensure your objects get cleaned up, and put some thought into implementing the appropriate level of exception safety in your RAII objects, so they're able to survive without special handling if an exception is thrown.
如果异常允许您的对象保留在无效状态,则异常只会造成问题。这绝对不会发生。您的对象应始终至少实现基本保证。 (和实现一个提供适当级别的异常安全性的容器类是一个有启发性的C ++练习))
Exceptions only really cause problems if they allow your objects to be left in an invalid state. That should never happen. Your objects should always implement at least the basic guarantee. (and implementing a container class which provides the proper level of exception safety is an enlightening C++ exercise ;))
关于文档,当你来确定功能可能抛出的某些异常,一切都可以自由地记录它。但一般来说,当没有指定任何其他内容时,假设函数可能会抛出。空的指定有时用于记录函数永远不会引用的时候。如果不在那里,假设函数可能会抛出。
As for documentation, when you're able to determine for certain which exceptions a function may throw, by all means feel free to document it. But in general, when nothing else is specified, it is assumed that a function may throw. The empty throw specfication is sometimes used to document when a function never throws. If it's not there, assume that the function may throw.