C++函数指针中的异常规范

4

代码:

#include<iostream>
using namespace std;

void foo() throw(char) {throw 'a';}

int main() try {

   void (*pf)() throw(float);
   pf = foo; // This should NOT work 
   pf();

}
catch(const char& c){cout << "Catched ::> " << c << endl;}

为什么即使foo的异常规范与函数指针pf不同,也可以将foo传递给pf?这是编译器的错误吗?


因为try-catch不是函数声明的一部分。 - Anirudha
2个回答

9
异常规范不参与函数类型。 更正: 正如其他答案所指出的那样,这确实是编译器的一个错误。众所周知,大多数编译器在实现异常规范时存在缺陷。此外,在C++11中已经被弃用。因此,请遵循Herb Sutter的建议,避免写异常规范:

道德准则1:永远不要编写异常规范。

道德准则2:除非可能是空的,但如果我是你,我会避免甚至那样做。


1
因此,指向函数的异常规范仅用于让客户端知道该指针指向可能仅会抛出某些特定类型的函数。话虽如此,您可以像上面的示例一样说谎,并指向抛出其他类型的函数。如果我说错了,请纠正我。谢谢。 - AlexDan
@AlexDan:是的,你必须阅读Herb在答案中标记的优秀GOTW内联。 - Alok Save
你读了你发布的链接吗?它说你不能在typedef中使用异常规范,但是声明的函数指针必须具有兼容的异常规范! - Rost
@Als:IBM的一篇关于异常规范的文章表示相反的意见,请阅读其中讨论函数指针的部分:http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Ffunction_try_block_handlers.htm - AlexDan
@AlexDan 异常规格说明 参与 函数类型。它们不能在typedef中指定。所以这是你编译器的错误。有关详细信息,请参阅我的答案。 - Rost

5
是的,这是编译器错误。函数指针必须具有兼容的异常规范才能被分配。
标准中的引用:
15.4 异常规范 (5)...对于函数指针、成员函数指针和函数引用的赋值和初始化也存在类似的限制:目标实体应至少允许在赋值或初始化时源值允许的异常。
示例:
class A;

void (*pf1)(); // no exception specification
void (*pf2)() throw(A);

pf1 = pf2; // OK: pf1 is less restrictive
pf2 = pf1; // error: pf2 is more restrictive

您的代码使用Comeau编译时出现了不兼容的异常规范错误:

Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 9: error: incompatible exception specifications
  pf=foo; // This should NOT work 
    ^

正如许多人提到的那样,在C++11标准中,异常规范已被弃用(请参见附录D.4),除了noexcept规范外。因此,最佳实践是(并且一直是)- 避免使用异常规范


1
+1 因为你的观点似乎是正确的,但我想补充一点,即异常规格说明在 C++11 中已被弃用。有很多反对它们的论点,遵循 Herb Sutter 的建议似乎是明智的选择。 - Rook
@Rost:我成为你的粉丝了!再次给出了非常准确的答案。继续保持好工作! - Matthieu M.
@MatthieuM。非常感谢您的好评!我会尽力而为 :-) - Rost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接