首页 > 解决方案 > 虚函数的更宽松的抛出说明符:GCC 4.9 抱怨但 MSVC

问题描述

我有原始的 C++ 11 代码,它是为 Windows 开发的,可以由 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 编译我得到了错误

'virtual void D2::myFunc()' 的更宽松的抛出说明符

“throw()”添加到D2::MyFunc代码可以编译,但它不是 MyFunc 的预期属性。
有什么方法可以让 GCC 工作?

标签: c++c++11

解决方案


gcc 是对的;派生类中的虚函数不能具有比基类中被覆盖的函数更宽松的异常说明符。原因很清楚:如果允许,调用者可以通过基类指针调用覆盖函数,因此获取函数不尊重调用它的静态类型的异常契约。

在 MSVC 上,这恰好起作用,只是因为它对异常说明符的支持大大减少了 - 它实际上只解析throw(),所有其他异常说明符都被忽略了。

throw()现在,鉴于(AKA )以外的异常说明符nothrow

  • 在 MSVC 中被忽略
  • 无论如何都已从标准中弃用
  • 被广泛认为是一个错误,因为它们给你带来了几乎零编译时安全性——它们本质上归结为用一个 big 包装所有带注释的函数,并在抛出任何意外情况时try调用std::unexpected——甚至在 Java 风格的检查异常上也是如此麻烦是否真的值得被广泛争论;

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


推荐阅读