C++ 重写函数的异常规范比基本版本更宽松
我想自定义一个异常类,代码如下:C++ 重写函数的异常规范比基本版本更宽松,c++,exception,c++14,C++,Exception,C++14,我想自定义一个异常类,代码如下: class TestException : std::exception{ public: const char *what() const override { return "TestException"; } }; 我使用了Clion,IDE在函数what()上给了我一个警告:覆盖函数的异常规范比基本版本更宽松 但是如果我用gcc构建代码,就不会出现任何警告。 我用C++ 14,GCC 5.5.0 有人能解释一下警告的含义吗?我能忽略
class TestException : std::exception{
public:
const char *what() const override {
return "TestException";
}
};
我使用了Clion,IDE在函数what()
上给了我一个警告:覆盖函数的异常规范比基本版本更宽松
但是如果我用gcc构建代码,就不会出现任何警告。
我用C++ 14,GCC 5.5.0
有人能解释一下警告的含义吗?我能忽略它吗?
自C++11以来,std::exception
的成员函数被声明为noexcept
。因此,您也应该使覆盖的what
noexcept
。(实际上,这就是错误消息所说的。)
请注意,noexcept
关键字必须位于override
关键字之前(请参见,例如,了解详细信息)。您面临的警告与您正在使用C++14这一事实有关,如果您要使用C++17编译,则这将成为一个错误。因此,我不建议忽略它
发生什么事了
std::exception
将方法what
定义为:virtual const char*what()const noexcept代码>。您继承此方法并重新实现它,而不指定noexcept
。结果是,您告诉您的实现可以抛出异常,而基本方法指出这不应该抛出异常。(打电话的人会这样认为)
这在C++17中已修复,它使noexcept
成为类型系统的一部分,并要求您修复此代码:
const char *what() const noexcept override
fromstd::exception
是一个虚拟
函数,派生类中的虚拟
函数的异常规范不能比它在基类中重写的函数更宽松
本标准“例外规范”一节中提到了这一点
18.4例外规范[例外.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
};
D::f
的声明格式不正确,因为它具有潜在的引发异常规范,而B::f
具有非引发异常规范
解决方案是更改代码,如:
class TestException : std::exception{
public:
const char *what() const noexcept override {
return "TestException";
}
};
请参见此处。可能是缺少noexcept
?作为旁注,我建议继承std::logic_error
或std::runtime_error
,它更具体,还允许您在构造时正确设置错误消息。基类负责what()
。惰性格式通常是一个坏主意,因为(例如)我在对P.W.答案的评论中给出的原因。你没有提到的是What()
是noexcept
的一个非常明显的原因–在试图找出其他异常是什么的时候引发异常会非常烦人。这强烈阻止了对异常消息的延迟格式化,这也可能是为什么what()
不返回std::string
(复制时可能会抛出)。