虚拟函数的较宽松的抛出说明符:GCC 4.9抱怨但MSVC

时间:2018-12-11 05:44:04

标签: c++ c++11

我有为Windows开发的原始C ++ 11代码,可以通过MSVC进行编译:

 class Base
{
    virtual void myFunc() throw (std::runtime_error) = 0;
};

class D1 : public Base
{
    void myFunc() throw(std::runtime_error) override
    { //
        throw std::runtime_error("This method is not supported in this class so we throw exeception");
    }
};

class D2 : public D1
{
    void myFunc() override
    {
        //real implementation here
    }
};

代码已移植到Linux并使用GCC 4.9编译,但出现错误

  

针对“虚拟无效idcsim :: D2 :: myFunc()”的更宽松的抛出说明符

D2 :: MyFunc 中添加'throw()'可以编译代码,但这不是MyFunc的预期属性。
有什么办法可以让GCC发挥作用吗?

1 个答案:

答案 0 :(得分:3)

gcc是正确的;派生类中的虚函数不能具有比基类中要覆盖的函数更宽松的异常说明符。原因很明显:如果允许,则调用者可以通过基类指针调用重写函数,从而使函数不遵守调用该类型的静态类型的异常合同。

在MSVC上,这种工作之所以发生是因为它大大减少了对异常说明符的支持-它实际上仅解析throw(),而所有其他异常说明符都被忽略了。

现在,考虑到除throw()(又名nothrow)以外的异常说明符:

  • 在MSVC中被忽略
  • 无论如何,
  • 已不符合标准
  • 被广泛认为是一个错误,因为它们为您提供了几乎零的编译时安全性-本质上讲,它们归结为用大的try包装所有带注释的函数,并在发生意外情况时调用std::unexpected引发-甚至就Java样式检查的异常而言,是否确实值得解决该问题也广受争议;

您可能应该完全放下它们,并且永远不要回头。