尽管该主题已在 SO 上进行了广泛讨论,但考虑到以下事实,我想澄清一些我仍然不清楚的事情:
10 年前,Herb Sutter 告诉我们不要使用此功能。
指定函数/方法可能抛出的可能异常不会迫使编译器在您决定更改函数的主体并抛出新类型的异常时对您大喊大叫,从而错误地忘记更改函数声明中的异常规范。
如果你有一个非常高级的函数调用其他几个高级函数,每个函数都运行大量代码来产生结果,那么我可以想象地狱噩梦的维护,当我必须指定第一个函数的所有错误时可能会抛出,并且这个列表必须包括内部函数可能抛出的所有异常等等,从而在高级和低级函数之间产生紧密耦合,这是非常不可取的。另一方面,我们从 std::runtime_error 派生所有异常,我们知道这是一个好习惯我们可以指定高级函数只抛出 std::runtime_error 并完成它。但是等一下……我们实际上在哪里捕获异常?当高级函数应该只抛出 std::runtime_error 时,将对这些高级函数之一的调用包含在 try / catch 块中会不会很奇怪/讨厌/不好,该块会捕获 MyVerySpecific 异常? ? 在较低级别的函数中捕获特定异常是否有好处,这些函数无法对它们做任何事情,而是将它们传递到更通用的容器中,并附加更多信息?我当然不想在我编写的每个函数中都编写 try / catch 块,只是为了格式化异常。这就像要求每个函数都验证它的参数,这会让人发疯,
问题:
Herb Sutter 关于异常规范的咆哮今天仍然成立吗?从那以后有什么改变吗?我最感兴趣的是 pre-C++0x 标准。如果是,我想我们可以考虑关闭这个话题。
由于编译器似乎大多忽略了这些异常规范,并且在捕获异常时,在 99% 的情况下,人们会使用
catch (const CustomException &ex)
,如何指定函数抛出 CustomException?throw(CustomExecption)
或throw (CustomException &)
或throw (const CustomException &)
? 我已经看到了所有的变化,虽然我会选择第一个,但其他的有什么意义/增加任何好处吗?人们将如何实际使用此功能,同时避免上述第三个事实中说明的谬误?
编辑:假设我们正在建立一个图书馆。如果我们不使用异常规范,它的用户将如何知道预期的异常?他们肯定不会看到 API 方法会在内部调用哪些函数……