为什么在编译时不检查C++异常规范?

Tar*_*ral 8 c++ exception exception-specification c++11

我刚才读到,在C++ 11标准版本中,异常规范已被弃用.我以前认为指定你的功能可能是好的做法,但显然,不是这样.

在阅读了Herb Stutter引用得很好的文章之后,我不禁要问:为什么实际上是按照它们的方式实现了异常规范,为什么委员会决定弃用它们而不是在编译时检查它们?为什么编译器甚至允许抛出一个未出现在函数定义中的异常?对我来说,这听起来像是在说"你可能不应该指定你的函数返回类型,因为当你指定时int f(),但return 3.5;在它内部,你的程序可能会崩溃." (即强类型的概念差异在哪里?)

(由于typedefs中缺少异常规范支持,假设模板语法可能是Turing-complete,实现这个听起来很容易.)

Jam*_*nze 11

最初的原因是,鉴于现有代码的主体,以及没有说明符意味着任何东西可以抛出的事实,认为不可能可靠地检查.这意味着如果静态检查有效,则以下代码将无法编译:

double
safeSquareRoot( double d ) throw()
{
    return d > 0.0 ? sqrt( d ) : 0.0;
}
Run Code Online (Sandbox Code Playgroud)

此外,异常的目的是报告远距离的错误,这意味着中间函数不应该知道它们调用的函数可能抛出的内容.在它们上需要异常说明符会破坏封装.

函数需要了解可能发生的异常的唯一真实情况是知道哪些异常不会发生.特别是,除非可以保证某些函数永远不会抛出,否则不可能编写线程安全代码.即使在这里,由于上面解释的原因,静态检查也是不可接受的,因此异常规范的设计更像是一个你无法停用的断言:当你写的时候throw(),你或多或少相当于一个断言失败,如果函数由异常终止.

Java中的情况有所不同.在Java中,没有真正的输出参数,这意味着如果函数也有返回值,则不能使用返回码.结果是在许多情况下使用异常,其中返回代码更可取.而这些,您必须了解并立即处理.对于那些应该是异常的东西,Java有java.lang.RuntimeException (没有经过检查,静态或其他方式).它没有办法说函数不能抛出异常; Error在中止程序更合适的情况下,它还使用未经检查的异常(被调用).


Har*_*son -1

如果函数f() throw(int)调用函数g() throw(int, double)会发生什么?

编译时检查将阻止您的函数调用具有不太严格的抛出说明符的任何其他函数,这将是一个巨大的痛苦。