C++中的内联throw()方法

6

我正在尝试定义一个非常简单的异常类。因为它非常简单,我只想将其保留在.h文件中,但编译器不喜欢throw()。代码如下:

#include <exception>
#include <string>

class PricingException : public virtual std::exception
{
private:
    std::string msg;
public:
        PricingException(std::string message) : msg(message) {}
        const char* what() const throw() { return msg.c_str(); }
        ~PricingException() throw() {}
};

GCC 给出以下错误:

/home/ga/dev/CppGroup/MonteCarlo/PricingException.h:13: error: expected unqualified-id before ‘{’ token
/home/ga/dev/CppGroup/MonteCarlo/PricingException.h:14: error: expected unqualified-id before ‘{’ token

针对带有throw()的行,有什么解决方法吗?

编辑

我尝试删除有问题的方法的内容,即:

virtual ~PricingException() throw();// {}

现在我收到了更奇怪的错误信息:

/home/ga/dev/CppGroup/MonteCarlo/PricingException.h:14: error: looser throw specifier for ‘virtual PricingException::~PricingException()’
/usr/include/c++/4.5/exception:65: error:   overriding ‘virtual std::exception::~exception() throw ()’

它只是忽略了我的throw说明符!


#include <exception> ? #include <string> ? - CB Bailey
1
你的代码在gcc 3.4、4.2和gcc 4.4上编译没有问题。你是否关闭了一些异常特性?或者你使用的是旧版本? - Mark B
2
代码看起来没有问题。但是为什么你在这里使用虚继承? - Serge Dundich
@Serge:这是Stroustrup推荐的。 - Matthieu M.
4
可能有一个不同的头文件正在使用预处理器来重新定义 throw(这是一种非常恶劣的做法,但并非闻所未闻)。您可以使用 g++ -E 命令查看预处理后的源代码,并检查在它们到达编译器时 throw() 规范是否仍然完好无损。 - Mike Seymour
显示剩余8条评论
5个回答

4

可以尝试使用 C++0x 语法,g++ 4.5 可能已经支持:

const char* what() const noexcept { return msg.c_str(); }

然而,这并不重要(来自草案3242,第
[except.spec]节的措辞):
两个异常规范兼容的,如果:
  • 两者都是非抛出的(见下文),无论它们的形式如何,
  • 两者具有形式noexcept(常量表达式)并且常量表达式是等效的,
  • 一个异常规范是允许所有异常的noexcept规范,另一个是形式为throw(type-id-list),或者
  • 两者都是具有相同调整类型集合的动态异常规范
如果虚函数具有异常规范,则任何派生类中覆盖该虚函数的任何函数的所有声明,包括定义,都只允许由基类虚函数的异常规范允许的异常。
没有异常规范或形式为noexcept(常量表达式)常量表达式为false的异常规范允许所有异常。如果异常规范的形式为throw()noexceptnoexcept(常量表达式)常量表达式true,则该函数是非抛出的。具有非抛出的异常规范的函数不允许任何异常。
因此,请尝试使用更新的g++构建,其中这些更改可能得到更完整的实现。

刚刚确认使用clang ToT和g++ 4.5.2(mingw版本)工作良好。 - Matthieu M.

3
我在C++0x中找到的最接近的内容是:
15.4 异常规格说明 [except.spec]
2 异常规格说明只能出现在函数类型、函数指针类型、函数类型的引用或成员函数类型的顶层声明或定义,或作为这样的类型在函数声明符的参数或返回类型中。看起来像是不允许在定义中使用异常规格说明。

每个定义都是一个声明,不是吗? - Ben Voigt
即使引用的段落中提到了“或定义”,也是如此。 - CB Bailey
@Ben Voigt:我会这么说,因此“could disallow”表示我不确定如何解释这一段。如果有更有经验的人提供意见,我会很高兴。我的回答旨在为讨论带来些许帮助,而不是结束讨论 :) - Matthieu M.
@Ben Voigt:是的,我看到了这个,这就是为什么我想知道它发生的原因。我开始怀疑可能是一个有缺陷或者不是最新实现的问题,因为我认为在草案的演变过程中措辞已经改变了。 - Matthieu M.
@Matthieu:我同意,这可能是该特定版本中的一个错误/部分完成的实现。 - Ben Voigt
显示剩余2条评论

1

我无法在几个版本的g++中重现这个问题。最有可能的问题是之前包含的头文件存在问题,当编译器看到throw时才会出现麻烦。


0
你尝试过在不加括号的情况下使用throw吗?在这个例子中(我知道它在.cpp文件中),但你会发现所有的throw都没有括号。

http://www.glenmccl.com/eh_cmp.htm


在页面底部,他们说:“带有throw()的函数根本不允许抛出异常。” - Grzenio
2
这些是异常规范,而不是抛出表达式,并且需要括号。 - Mike Seymour

0

终于找到了!@Mike Seymour的评论是正确的 - 原来在一个文件nr3.h(Numerical Recepies代码的一部分)中定义了宏throw(message)

我不明白的是为什么会影响不包含此.h 文件的文件的编译...

无论如何,我认为Visual Studio有一个不同的编译顺序或者类似的原因,所以它在那里编译是纯粹的运气,而不是在gcc下编译。


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