【问题标题】:Inline throw() method in C++C++ 中的内联 throw() 方法
【发布时间】:2011-03-29 12:52:46
【问题描述】:

我正在尝试定义一个非常简单的异常类。因为它非常简单,我只想将它保存在 .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 ()’

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

【问题讨论】:

  • 使用 gcc 4.2.1 版(Apple Inc. build 5664)在这里编译得很好
  • 我正在运行gcc (Debian 4.5.2-4) 4.5.2
  • 您的代码在 gcc 3.4、4.2 和 gcc 4.4 下编译得很好。您是否关闭了一些异常功能?您使用的是旧版本吗?
  • 在代码中似乎没有问题。但是为什么你在这里使用虚拟继承呢?
  • 可能一个不同的头文件正在使用预处理器重新定义throw(一个彻底的邪恶做法,但并非闻所未闻)。您可以使用g++ -E 查看预处理后的源代码,并检查throw() 规范在到达编译器时是否仍然完好。

标签: c++ gcc throw


【解决方案1】:

尝试使用 C++0x 语法,g++ 4.5 可能足够新以支持它:

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

但是,这应该没关系(措辞来自草案 3242,[except.spec] 部分:

两个异常规范兼容的如果:

  • 无论其形式如何,两者都不会投掷(见下文),
  • 两者都具有noexcept(constant-expression) 的形式,并且 constant-expressions 是等价的,
  • 一个exception-specification是一个noexcept-specification,允许所有异常,另一个是throw(type-id-list),或
  • 两者都是动态异常规范,具有相同的调整类型集。

.

如果虚函数具有异常规范,则在任何派生类中覆盖该虚函数的任何函数的所有声明(包括定义)都应只允许允许的异常>异常规范基类虚函数。

.

没有异常规范或具有noexcept(常量表达式)形式的异常规范的函数,其中constant-expression 产生 false 允许所有异常。 异常规范非抛出如果它是throw()noexceptnoexcept(常量表达式)的形式,其中常量表达式 产生true。具有不抛出异常规范的函数不允许任何异常。

所以尝试更新版本的 g++,这些更改可能会更完整地实现。

【讨论】:

  • 刚刚确认它在 clang ToT 和 g++ 4.5.2(mingw 版本)上运行良好。
【解决方案2】:

我在 C++0x 中找到的最接近的是:

15.4 异常规范 [except.spec]

2 异常规范应仅出现在函数类型的函数声明符、指向函数类型的指针、对函数类型的引用或指向作为声明或定义的顶级类型的成员函数类型的指针上,或在函数声明器中作为参数或返回类型出现的这种类型。

在我看来,它可能不允许在定义上使用异常规范。

【讨论】:

  • 每个定义都是一个声明,不是吗?
  • 即使引用的段落也说“或定义”。
  • @Charles:我会将它与之前的内容相关联:“或指向作为声明或定义的顶级类型的成员函数类型的指针”,因为它后面跟着一个逗号和另一个成员的替代方案。
  • @Ben Voigt:我会这么说,因此可能不允许,因为我不确定如何解释这篇文章。我会很高兴有更多经验的人加入,我的回答是为了给工厂带来一些水,而不是结束讨论:)
  • @Matthieu:不仅如此,定义需要携带一个与声明匹配的exception-specification。阅读同一部分的第 4 段。
【解决方案3】:

我无法在多个版本的 g++ 中重现这一点。最可能的问题是,以前包含的头文件有一个问题,当它看到 throw 而不是之前,最终导致编译器出现问题。

【讨论】:

    【解决方案4】:

    您是否尝试过不带 () 的 throw?在这个例子中(我知道它在 .cpp 文件中),但你看到所有的 throws 都没有括号

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

    【讨论】:

    • 在哪里?在页面底部他们说one with: throw() is not allowed to throw exceptions at all.
    • 这些是异常规范,不是 throw 表达式,需要括号。
    【解决方案5】:

    终于找到了! @Mike Seymour 在他的评论中是对的 - 事实证明,在文件 nr3.h(Numerical Recepies 代码的一部分)中定义了一个宏 throw(message)

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

    无论如何,我认为 Visual Studio 有不同的编译顺序或其他东西,所以它在那里编译而不是在 gcc 下编译纯粹是运气。

    【讨论】:

      猜你喜欢
      • 2012-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      • 2013-04-26
      • 1970-01-01
      相关资源
      最近更新 更多