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

rea*_*esk 9 c++ exception c++14

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

class TestException : std::exception{
  public:
  const char *what() const override {
    return "TestException";
  }
};
Run Code Online (Sandbox Code Playgroud)

我使用Clion和IDE给我一个警告what():exception specification of overriding function is more lax than base version

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

任何人都可以帮助解释警告意味着什么,我可以忽略它吗?

P.W*_*P.W 7

whatfrom std::exception是一个virtual函数,virtual派生类中的函数不能比它在基类中重写的函数具有更宽松的异常规范.

这在标准中的"例外规范"一节中提到.

18.4异常规范[except.spec]
...
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 
}; 
Run Code Online (Sandbox Code Playgroud)

声明D::f是不正确的,因为它具有潜在抛出的异常规范,而B::f具有非抛出异常规范.

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

class TestException : std::exception{
  public:
  const char *what() const noexcept override {
    return "TestException";
  }
};
Run Code Online (Sandbox Code Playgroud)

请参见此处的汇编.


Dan*_*ica 6

what成员函数std::exception声明为noexcept自C++ 11以来.因此你也应该让你被覆盖what noexcept.(实际上,这是错误消息所说的.)

请注意,noexcept关键字必须位于关键字之前override(有关详细信息,请参阅标准中的覆盖顺序和noexcept).