什么是';覆盖';C++;用来做什么? 我是C++初学者。我遇到了我正在处理的头文件中使用的override关键字。我想知道,override的真正用途是什么,也许通过一个例子就很容易理解了。

什么是';覆盖';C++;用来做什么? 我是C++初学者。我遇到了我正在处理的头文件中使用的override关键字。我想知道,override的真正用途是什么,也许通过一个例子就很容易理解了。,c++,c++11,overriding,C++,C++11,Overriding,override是一个C++11关键字,这意味着一个方法是来自基类的方法的“override”。考虑这个例子: class Foo { public: virtual void func1(); } class Bar : public Foo { public: void func1() override; } 如果B::func1() 它向代码的读者显示“这是一个虚拟方法,它正在重写基类的虚拟方法。” 编译器

override
是一个C++11关键字,这意味着一个方法是来自基类的方法的“override”。考虑这个例子:

   class Foo
   {
   public:
        virtual void func1();
   }

   class Bar : public Foo
   {
   public:
        void func1() override;
   }

如果
B::func1()

  • 它向代码的读者显示“这是一个虚拟方法,它正在重写基类的虚拟方法。”
  • 编译器还知道它是一个重写,因此它可以“检查”您是否正在更改/添加您认为是重写的新方法 为了解释后者:

    class base
    {
      public:
        virtual int foo(float x) = 0; 
    };
    
    
    class derived: public base
    {
       public:
         int foo(float x) override { ... } // OK
    }
    
    class derived2: public base
    {
       public:
         int foo(int x) override { ... } // ERROR
    };
    
    derived2
    中,编译器将发出“更改类型”错误。如果没有
  • 覆盖,编译器最多会发出警告“您正在用相同的名称隐藏虚拟方法”

    维基百科说:

    在面向对象编程中,方法重写是一种语言特性,它允许子类或子类提供已由其一个超类或父类提供的方法的特定实现

    具体地说,当您有一个对象foo具有void hello()函数时:

    class foo {
        virtual void hello(); // Code : printf("Hello!");
    }
    
    class bar : foo {
        // no functions in here but yet, you can call
        // bar.hello()
    }
    
    foo的子级还将具有hello()函数:

    class foo {
        virtual void hello(); // Code : printf("Hello!");
    }
    
    class bar : foo {
        // no functions in here but yet, you can call
        // bar.hello()
    }
    
    但是,当从Bar对象调用Hello()函数时,可能需要打印“Hello Bar!”。您可以使用覆盖来完成此操作

    class bar : foo {
        virtual void hello() override; // Code : printf("Hello Bar!");
    }
    

    作为所有答案的补充,仅供参考:
    override
    不是一个关键字,而是一种特殊的标识符!它只有在声明/定义虚拟函数的上下文中才有意义,在其他上下文中它只是一个普通的标识符。有关详细信息,请参阅本标准的2.11.2


    注意c++11还引入了
    final
    关键字。@JesseGood再次强调:
    final
    也不是关键字@ZAFIA:它是从java的<> > >凌驾中激发出来的,让编译器根据C++规范对你进行编译时检查,“超越”是一个“具有特殊意义的标识符”。但是C#中的这些东西被称为上下文关键字。我认为这段代码中有一些不正确的地方。为了让编译器发出错误,派生类Bar中的签名必须不同,如
    void func1(int v)override
    以便编译器发出类似“标记的”override但不重写的错误。IOW:奇怪的是,重写似乎是编译器在派生类中使用的一个提示,用于验证基类中是否存在相同的签名。请参阅上面的答案。它有效(此处和对于
    final
    ),因为您不能在放置这些上下文关键字的位置使用常规标识符。为什么它不被禁止?@ferencedajka 1。为什么会这样?2.突然添加一个新关键字(即禁止在其他地方使用)会破坏向后兼容性。顺序还是普通?@krubo“标准”一词指的是国际上正式认可的东西。例如,一米的定义是一个标准,你不需要用超驰标识符来做C++,它只是强制你做的很好。嗨,事实上,维基百科的概念是一个好的基础,但正如鹅所说的那样。C++的细节添加了一个扭曲:它在派生类中使用,以帮助编译器识别代码中的问题,在这种情况下,虚拟函数存在于基中。魔鬼在于细节。参见上面的注释。在derived2类中,*foo*的函数头不应该类似吗??我用VS2017编译了这个,得到了一个编译错误。我的意思是inderived2 foo的头必须是:*int foo(float x)override{…}*嗯,这完全是问题所在,代码示例显示了如何使用override来检测错误!我认为#3是可以使用override来检测要重写的函数(属于父类/接口)是否被删除(而不是替换)。如果子类期望回调,但由于库的更改等原因,回调永远不会发生,那么这很有用。我认为编译器在不扫描所有调用图的情况下无法做到这一点,如果编译器做到了这一点,它就不需要
    重写
    ,就可以理解这一点。要做到这一点真的很难。