为什么编译器检查C ++中的exception?
C ++提供了检查exception的语法,例如:
void G() throw(Exception); void f() throw();
但是,Visual C ++编译器不检查它们; 抛标志简单地被忽略。 在我看来,这使得exceptionfunction无法使用。 所以我的问题是: 有没有办法让编译器检查exception是否正确捕获/ rethrown? 例如一个Visual C ++插件或一个不同的C ++编译器。
PS。 我希望编译器检查exception是否被正确捕捉,否则最终会出现这样的情况: 即使明确声明不会抛出任何东西 ,也不得不绕过每个函数调用。
更新:当使用throw()标记函数时,Visual C ++编译器会显示警告。 这很好,但遗憾的是,当你调用一个可能抛出的子程序时,这个警告不会显示出来。 例如:
void f() throw(int) { throw int(13); } void h() throw() { g(); } //no warning here!
在C ++中exception规范是没用的。
没有强制执行其他exception,只是全局函数unexpected()
会被调用(可以设置)
使用exception规范主要归结为欺骗自己(或你的同事)成为一种虚假的安全感。 最好不要干扰。
有趣的是,Java已经检查了exception,Java程序员也讨厌这些exception。
C ++中的exception规范是无用的,原因有三:
1. C ++exception规范禁止优化。
除了throw()之外,编译器会插入额外的代码来检查当你抛出一个exception时,它在堆栈展开期间匹配函数的exception说明。 让你的程序变慢的方法。
2. C ++exception规范不是编译器强制的
就你的编译器而言,下面的语法是正确的:
void AStupidFunction() throw() { throw 42; }
更糟糕的是,如果违反了exception规范,没有什么用处。 你的程序只是终止!
3. C ++exception规范是函数签名的一部分。
如果你有一个虚拟函数的基类,并试图覆盖它,exception规范必须完全匹配。 所以,你最好提前计划,这仍然是一个痛苦。
struct A { virtual int value() const throw() {return 10;} } struct B : public A { virtual int value() const {return functionThatCanThrow();} // ERROR! }
例外规范给你提供这些问题,并且使用它们的收益是最小的。 相反,如果完全避免exception规范,则编码更容易,而且避免了这种情况。
看看这个:
http://www.gotw.ca/publications/mill22.htm
基本的exception规范是不可行的/不可用的,但是这并不能使exception行不通。
至于你的问题,没有办法让编译器检查每一个抛出的types都被捕获在代码中的更高的地方,我期望编译单元使这个困难,这是不可能的代码打算在库中使用(在编译时顶层不可用)。 如果你想确保一切都被捕获,然后在你的代码最上面贴一个catch(…)。
要检测运行时之前的情况下,如…
extern void f() throw (class Mystery); void g() throw() { f() ; }
…你需要静态分析 。 是的,编译器正在做大量的静态分析,但是因为标准是“如果throw不匹配会引发std :: unexpected”,写一个抛出一个不符合说明符的对象的例程是完全合法的,编译器实现既不警告也不评论。
声称提供警告服务的静态分析工具包括Gimpel Software 针对C ++的皮棉 …
1560未捕获exception“名称”不在函数“符号”的throw-list上
并根据这个问题的答案 , QA C ++ 。
因为标准是这样说的。 exception声明并不意味着不会抛出其他exception。 这意味着如果抛出一个未声明的exception,将会调用一个名为unexpected()的特殊全局函数,该函数默认终止程序。 通常在函数中声明exception是不鼓励的(可能除了空的exception列表),因为标准的行为不是很有帮助。
我无法检查这是否缺乏MSVC安装,但你真的确定编译器忽略throw()规范?
这MSDN页面build议微软知道throw(),并期望他们的编译器正确处理它。 那么,几乎可以看到有关他们如何脱离ANSI / ISO标准的说明。
编辑:虽然,在实践中,我同意帕特里克:exception规格大多是无用的。