覆盖函数的异常规范比基本版本更宽松

时间:2018-12-18 09:24:18

标签: c++ exception c++14

我想自定义一个Exception类,这是代码:

class TestException : std::exception{
  public:
  const char *what() const override {
    return "TestException";
  }
};

我曾经使用过Clion,IDE则对功能what()exception specification of overriding function is more lax than base version

发出警告

但是,如果我使用gcc构建代码,则不会发出警告。 我用的是c ++ 14,gcc 6.5.0

有人可以帮助解释警告的含义吗,我可以忽略它吗?

3 个答案:

答案 0 :(得分:6)

自C ++ 11起,what

std::exception成员函数被声明为noexcept。因此,您还应该使被覆盖的what noexcept也是如此。 (实际上,这就是错误消息的内容。)

请注意,noexcept关键字必须位于override关键字之前(有关详细信息,请参见The order of override and noexcept in the standard)。

答案 1 :(得分:5)

std::exception中的

whatvirtual函数,并且派生类中的virtual函数不能具有比函数宽松的 exception规范它在基类中重写。

在标准的“异常说明”部分中提到了这一点。

  

18.4异常规范[spec.except除外]
  ...
  4.如果虚函数具有非抛出异常规范,则在任何派生类中覆盖该虚函数的任何函数的所有声明(包括定义)都应具有非抛出异常规范,除非将超越函数定义为已删除。

给出的示例(与问题中的代码有些相似)也对此进行了说明。

struct B 
{ 
  virtual void f() noexcept; 
  virtual void g(); 
  virtual void h() noexcept = delete; 
};
struct D: B 
{ 
  void f(); // ill-formed 
  void g() noexcept; // OK 
  void h() = delete; // OK 
}; 
  

D::f的声明格式错误,因为它具有可能抛出的异常说明,而B::f有一个非抛出的异常说明。

解决方案是更改代码,例如:

class TestException : std::exception{
  public:
  const char *what() const noexcept override {
    return "TestException";
  }
};

在此处查看compilation

答案 2 :(得分:1)

您面临的警告与您正在使用C ++ 14的事实有关,如果您将使用C ++ 17进行编译,则这将成为错误。因此,我不建议您忽略它。

怎么回事?

std::exception将方法what定义为:virtual const char* what() const noexcept;。您从该方法继承,然后在不指定noexcept的情况下重新实现它。结果是,您告诉您的实现可以抛出异常,而基本方法指示此异常不应抛出。 (呼叫者会这样假设)

此问题已在C ++ 17中修复,这使noexcept成为类型系统的一部分,并要求您修复以下代码:

const char *what() const noexcept override