我只花了几个小时通读了关于何时使用异常的问题,似乎有两个不同观点的阵营:
I just spent a few hours reading through SO questions on the topic of when to use exceptions, and it seems like there are two camps with different point of views:
这只是一个有争议的话题,没有被广泛接受的最佳实践吗?
Is this just a controversial topic with no widely accepted best practice?
正如您可能从大量答案中收集到的那样,肯定没有达成共识.
As you can probably gather from the wealth of answers, there is certainly no consensus.
在语义上,异常和错误提供完全相同的功能.实际上,它们在所有语义方面都是相同的,并且错误可以像异常一样任意丰富(您不必使用简单的代码,您可以使用真正的数据包!).
Semantically, exceptions and error provide the exact same functionality. Indeed they are identical in about all semantic aspects, and errors can be arbitrarily enriched much like exceptions (you don't have to use a simple code, you can use a real bundle of data!).
唯一的区别是它们的传播方法:
The only difference there is is their propagation methods:
另一方面:
这两种解决方案看起来笨拙的原因很简单,就是错误检查很困难.事实上,我每天编写的大部分代码都涉及错误检查,无论是技术性的还是功能性的.
The very reason both solutions can appear clunky is simply that error checking is difficult. Indeed most of the code I am writing daily concerns error checking, whether technical or functional.
那该怎么办?
警告:提前演示,如果您只关心答案,请跳到下一部分
我个人喜欢在这里利用类型系统.典型的例子是指针引用二分法:指针就像一个可以为空的引用(并重新设置,但在这里无关紧要)
I personally like to leverage the type system here. The typical example is the pointer-reference dichotomy: a pointer is like a reference that can be null (and reseated, but it does not matter here)
因此,代替:
// Exceptions specifications are better not used in C++
// Those here are just to indicate the presence of exceptions
Object const& Container::search(Key const& key) const throw(NotFound);
我会倾向于写:
Object const* Container::search(Key const& key) const;
或者更好的是,使用聪明的指针:
Or better yet, using clever pointers:
Pointer<Object const> Container::search(Key const& key) const;
template <typename O>
O* Pointer<O>::operator->() const throw(Null);
template <typename O>
O& Pointer<O>::operator*() const throw(Null);
在这里我发现异常的使用是多余的,原因有两个:
Here I find the use of exception superfluous for 2 reasons:
我对异常本身没有问题,但它们会使代码变得笨拙,请考虑:
I don't have a problem with exceptions per se, but they can make the code awkward, consider:
void noExceptions(Container const& c)
{
Pointer<Object const> o = c.search("my-item");
if (!o) {
o = c.search("my-other-item");
}
if (!o) { return; } // nothing to be done
// do something with o
}
并将其与异常"情况进行比较:
And compare it with the "exception" case:
void exceptions(Container const& c)
{
Object const* p = 0;
try {
p = &c.search("my-item");
}
catch(NotFound const&) {
try {
p = &c.search("my-other-item");
}
catch(NotFound const&) {
return; // nothing to be done
}
}
// do something with p
}
在这种情况下,使用异常似乎并不合适:/
In this case, the use of exceptions does not seem appropriate :/
另一方面:
try {
print() << "My cute little baby " << baby.name() << " weighs " << baby.weight();
}
catch(Oupsie const&) {
// deal
}
肯定比:
if (!print("My cute little baby ")) { /*deal*/ }
if (!print(baby.name())) { /*deal*/ }
if (!print(" weighs ")) { /*deal*/ }
if (!print(baby.weight())) { /*deal*/ }
<小时>
什么是最好的?
这取决于.像所有工程问题一样,没有灵丹妙药,一切都与让步有关.
It depends. Like all engineering problem there is no silver bullet, it's all about concessions.
所以请记住两件事:
如果您发现自己想知道是否使用异常,请尝试使用您的 API.如果没有明确的赢家,那就是:没有理想的解决方案.
If you find yourself wondering whether to use an exception or not, just try to use your API. If there is no clear cut winner, it is just that: there is no ideal solution.
哦,当很明显在制作 API 时选择的错误报告机制不再合适时,请不要犹豫重构您的 API.不要感到羞耻:需求会随着时间的推移而变化,因此 API 随之变化是正常的.
Oh, and do not hesitate to refactor your API when it becomes clear that the error reporting mechanism elected at the time of crafting it is no longer appropriate. Don't be ashamed: requirements change with time, so it is normal that the API change with them.
就个人而言我倾向于仅将异常用于不可恢复的错误:因此,我的代码中很少有 try/catch,仅在最外层,以准确记录错误(喜欢堆栈帧)并记录也是 BOM 的转储.
Personally I tend to use exceptions for unrecoverable errors only: I therefore have few try/catch in my code, only in the outermost levels, to accurately log the error (love stack frames) and log a dump of the BOM as well.
这与 Haskell 非常相似(并且确实受到强烈影响),那里的代码分为两个清晰的部分:虽然任何部分都可以抛出异常,但只有 IO 部分(extern 部分)才能真正捕获它们.因此,纯部分必须以其他方式处理错误情况,以防它们正常".
This is very similar (and indeed strongly influenced) by Haskell, the code there is seggregated in two clear cut parts: while any can throw exceptions, only the IO part (the extern one) may actually catch them. Therefore, the pure part must deal with error conditions with other ways in case they are "normal".
但是,如果我面临使用异常使代码更易于阅读和自然(这是主观的)的问题,那么我使用异常:)
If, however, I am faced with a problem where using an exception makes the code easier to read and more natural (which is subjective) then I use an exception :)
这篇关于C++ 社区是否就何时应该使用异常达成普遍共识?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!