• 在c++ 11中, override specifier防止不覆盖预期的虚拟基函数(因为签名不匹配)。
  • final specifier可防止无意中覆盖派生类中的函数。

  • =>是否有一个说明符(例如firstno_override之类的东西)可以防止覆盖未知的基本函数?

    当虚拟函数被添加到具有与派生类中已经存在的虚拟函数相同签名的基类时,我想得到一个编译器错误。

    编辑4 :为了使这个问题简单和答案相关,这里再次是

    原始伪代码
  • 抽象class B : A具有private: virtual void fooHasBeenDone() = 0;
  • class C : B实现private: virtual void fooHasBeenDone() override { react(); }
  • 现在class A得到一个新的private: virtual void fooHasBeenDone();
  • 但是新的A::foo可能与原始的B::foo不同。


  • 还有一个具体的例子
  • 抽象class B : A具有用于测试PainterPath的virtual void showPath() = 0;
  • class C : B实现virtual void showPath() override { mPath.setVisible(); }
  • 现在,class A获得一个新的virtual void showPath();,这意味着文件路径
  • 现在,当A调用showPath()时,B将显示painterPath而不是某些文件路径。

  • 当然这是错误的,然后我应该将B::showPath()重命名为B::showPainterPath()并实现B::showPath() override。我只想从编译器那里得到信息。

    这是一个正在编译的真实示例:
    #include <iostream>
    #define A_WITH_SHOWPATH
    
    class A
    {
    #ifdef A_WITH_SHOWPATH
    public:
        void setPath(std::string const &filepath) {
            std::cout << "File path set to '" << filepath << "'. Display it:\n";
            showPath();
        }
        // to be called from outside, supposed to display file path
        virtual void showPath() {
            std::cout << "Displaying not implemented.\n";
        }
    #else
        // has no showPath() function
    #endif
    };
    
    class B : public A
    {
    public:
        virtual void showPath() = 0; // to be called from outside
    };
    
    class C1 : public B {
    public:
        virtual void showPath() override {
            std::cout << "C1 showing painter path as graphic\n";
        }
    };
    
    class C2 : public B {
    public:
        virtual void showPath() override {
            std::cout << "C2 showing painter path as widget\n";
        }
    };
    
    
    int main() {
        B* b1 = new C1();
        B* b2 = new C2();
    
        std::cout << "Should say 'C1 showing painter path as graphic':\n";
        b1->showPath();
        std::cout << "---------------------------\n";
        std::cout << "Should say 'C2 showing painter path as widget':\n";
        b2->showPath();
        std::cout << "---------------------------\n";
    
    #ifdef A_WITH_SHOWPATH
        std::cout << "Should give compiler warning\n or say \"File path set to 'Test'. Display it:\"\n and \"Displaying not implemented.\",\n but not \"C1 showing painter path as graphic\":\n";
        b1->setPath("Test");
        std::cout << "# Calling setPath(\"Test\") on a B pointer now also displays the\n#  PainterPath, which is not the intended behavior.\n";
        std::cout << "# The setPath() function in B should be marked to never override\n#  any function from the base class.\n";
        std::cout << "---------------------------\n";
    #endif
        return 0;
    }
    

    运行它,然后查看文本输出。

    作为引用,一个带有特定用例(PainterPath实例)的旧示例:

    https://ideone.com/6q0cPD(链接可能已过期)

    最佳答案

    firstno_override这样的说明符的功能就不存在了。可能是因为它可能造成困惑。但是,可以通过更改方法来轻松实现。

    应该在带有final说明符的基类中添加任何新方法。这将有助于获取任何匹配签名的编译器错误。因为,它将使后续派生类方法签名自动成为此类的“第一个”。稍后,可以将 final关键字删除,因为它仅用于“第一手验证”。

    在新添加的基本方法之后放置和删除final关键字类似于类似于使用debug(g++ -g)选项编译二进制文件,它可以帮助您修复错误。在生产中,为了优化而删除了调试选项。

    从您的示例:

    class A {};  // no method, no worry
    
    class B {
      public: virtual void showPath() = 0;  // ok
    };
    ...
    

    现在不小心在A中添加了类似的方法,这会导致错误:
    class A {
      public: virtual void showPath() final;  // same signature by chance
      // remove the `final` specifier once the signature is negotiated
    };
    class B {
      public: virtual void showPath() = 0;  // ERROR
    };
    

    因此,必须协商新A::showPath()和现有B::showPath()之间的签名,然后通过删除final说明符来继续进行签名。

    10-01 19:56