什么是相反的c ++`override` /`final`说明符? [英] What is the opposite of c++ `override` / `final` specifier?

查看:783
本文介绍了什么是相反的c ++`override` /`final`说明符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



=>是否有说明符(可能 no_override ),以防止覆盖未知的基本函数?



将一个虚拟函数添加到与派生类中已存在的虚拟函数具有相同签名的基类中。






EDIT 4 :为了简化这个问题并提供相关答案,请再次使用



原始伪码 / p>


  • 抽象 B类:A private:virtual void fooHasBeenDone()= 0;

  • class C:B implements virtual void fooHasBeenDone()override {react(); }

  • 现在 A类获得一个新的 private:virtual void fooHasBeenDone );

  • 但是新的 A :: foo 可能不同于原始的 B :: foo









  • 抽象 B类:A virtual void showPath()= 0; meaing a PainterPath

  • class C:B implements virtual void showPath()override {mPath.setVisible();现在 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<< 文件路径设置为<文件路径< '。显示:\\\
      ;
      showPath();
      }
      //从外部调用,应显示文件路径
      virtual void showPath(){
      std :: cout< 显示未实现。
      }
      #else
      //没有showPath()函数
      #endif
      };

      class B:public A
      {
      public:
      virtual void showPath()= 0; //从外部调用
      };

      class C1:public B {
      public:
      virtual void showPath()override {
      std :: cout< C1显示绘图路径为graphic\\\
      ;
      }
      };

      class C2:public B {
      public:
      virtual void showPath()override {
      std :: cout< C2 shows painter path as widget\\\
      ;
      }
      };


      int main(){
      B * b1 = new C1();
      B * b2 = new C2();

      std :: cout<< 应该说'C1显示画家路径为图形':\\\
      ;
      b1-> showPath();
      std :: cout<< --------------------------- \\\
      ;
      std :: cout<< 应该说'C2显示画家路径为小部件':\\\
      ;
      b2> showPath();
      std :: cout<< --------------------------- \\\
      ;

      #ifdef A_WITH_SHOWPATH
      std :: cout<< 应该给编译器警告\\\
      或说\文件路径设置为测试。显示它:\\\\
      和\显示未实现。\,\\\
      但不是\C1将绘图路径显示为图形\:\\\
      ;
      b1-> setPath(Test);
      std :: cout<< #在B指针上调用setPath(\Test\)现在还显示了\\\
      #PainterPath,这不是预期的行为。
      std :: cout<< #B中的setPath()函数应该被标记为从不覆盖基类的任何函数。\\\
      ;
      std :: cout<< --------------------------- \\\
      ;
      #endif
      return 0;
      }

      运行它并查看文本输出。






      作为参考,具有特定用例(PainterPath实例)的旧示例:



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

      解决方案

      这个答案是社区wiki,因为它结合了所有其他答案。




      1. 不,没有第一 no_override (answer)

      2. 覆盖 说明符。

        Qt有一个覆盖
        (如果可用)的Q_DECL_OVERRIDErel =nofollow>宏 Q_DECL_OVERRIDE 。 >
        如果不可用,至少用注释标记每个重写函数。

      3. 如果这样做, $ c> override

        Clang现在具有 -Winconsistent-missing-override ,而较新的GCC具有 -Wsuggest-override

        我不知道有VS2012标志。随意编辑。

      4. 您可以通过添加基类不知道的秘密来模仿所需的行为。 (answer)

        这在非常具体的用例中是有用的,但通常打破虚拟性的概念(见其他答案的评论)。

      5. 如果你不拥有基类<

      6. 如果您拥有基类, 您可以暂时向任何新的虚拟功能添加最后(answer)

        代码编译后没有错误,你知道在任何派生类中都没有该名称和签名的函数,你可以再次删除 final

      ...我想我会开始将虚拟函数标记为 DECL_FIRST 。也许在将来会有一个独立于编译器的方法来检查这个。


      • In c++11 the override specifier protects from not overriding an intended virtual base function (because the signatures do not match).
      • The final specifier protects from unintentionally overriding a function in a derived class.

      => Is there a specifier (something like maybe first or no_override) that protects from overriding an unknown base function?

      I'd like to get a compiler error when a virtual function was added to a base class with the same signature as an already existing virtual function in a derived class.


      EDIT 4: To keep this question simple and answers relevant, here is again the

      original pseudo-code

      • abstract class B : A has private: virtual void fooHasBeenDone() = 0;
      • class C : B implements private: virtual void fooHasBeenDone() override { react(); }
      • Now class A gets a new private: virtual void fooHasBeenDone();
      • But the new A::foo could be something different than the original B::foo.

      and a specific example

      • abstract class B : A has virtual void showPath() = 0; meaing a PainterPath
      • class C : B implements virtual void showPath() override { mPath.setVisible(); }
      • Now class A gets a new virtual void showPath(); meaning a file path
      • Now when A calls showPath(), B shows the painterPath instead of some file path.

      Of course this is wrong, and I should then rename B::showPath() to B::showPainterPath() and implement B::showPath() override as well. I'd just like to get informed by the compiler.


      Here is a compiling real-world example:

      #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;
      }
      

      Run it and look at the text output.


      For reference, an older example with a specific use-case (PainterPath instance):

      https://ideone.com/6q0cPD (link may be expired)

      解决方案

      This answer is community wiki because it combines all other answers. Please upvote the specific answer that was helpful to you as well as this one.

      1. No, there is no specifier like first or no_override. (answer)
      2. You should use the override specifier as often as possible.
        Qt has a macro Q_DECL_OVERRIDE that expands to override, if available.
        If not available, at least mark each overriding function with a comment.
      3. If you do that, there are compiler flags that warn about a missing override:
        "Clang now has -Winconsistent-missing-override, and newer GCCs have -Wsuggest-override."
        I don't know of a VS2012 flag for this. Feel free to edit.
      4. You can mimic the desired behavior by adding a 'secret' that the base class cannot know. (answer)
        This is helpful in very specific use cases, but generally breaks the concept of virtuality (see comments to the other answers).
      5. If you don't own the base class and have a conflict (e.g. compiler warning), you will need to rename your virtual function in all derived classes.
      6. If you own the base class, you can temporarily add a final to any new virtual function. (answer)
        After the code compiles without errors, you know that no function of that name and signature exists in any derived class, and you can remove the final again.

      ... I think I'll start marking first virtual functions as DECL_FIRST. Maybe in the future there will be a compiler-independent way of checking this.

      这篇关于什么是相反的c ++`override` /`final`说明符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆