覆盖方法时 virtual 关键字是啥意思?

Posted

技术标签:

【中文标题】覆盖方法时 virtual 关键字是啥意思?【英文标题】:What does the virtual keyword mean when overriding a method?覆盖方法时 virtual 关键字是什么意思? 【发布时间】:2011-06-18 16:31:10 【问题描述】:

virtual 关键字在重写方法时有什么作用?我没有使用它,一切正常。

每个编译器在这方面的行为是否相同?

我应该使用它还是不使用它?

【问题讨论】:

C++ Virtual/Pure Virtual Explained 的可能重复项 @Harald:不。不同的主题。 但我问的是该关键字的用法。与抽象虚拟方法无关。 派生类中的虚拟关键字是可选的,但最好跳过它。否则,如果您有很多派生类,并且想要将继承的方法之一设为虚拟,则必须在所有这些派生类中为该方法添加 virtual 关键字。 【参考方案1】:

没有它,您无法覆盖成员函数。

你只能隐藏一个。

struct Base 
   void foo() 
;

struct Derived : Base 
   void foo() 
;

Derived::foo覆盖Base::foo;它只是隐藏它,因为它具有相同的名称,如下所示:

Derived d;
d.foo();

调用Derived::foo

virtual 启用多态性,以便您实际上覆盖函数:

struct Base 
   virtual void foo() 
;

struct Derived : Base 
   virtual void foo()  // * second `virtual` is optional, but clearest
;

Derived d;
Base& b = d;
b.foo();

这会调用Derived::foo,因为它现在覆盖 Base::foo——你的对象是多态的。

(由于the slicing problem,您还必须为此使用引用或指针。)


Derived::foo 不需要重复 virtual 关键字,因为 Base::foo 已经使用了它。这是由标准保证的,您可以依赖它。不过,为了清楚起见,有些人认为最好保留这一点。

【讨论】:

我知道在声明可以被覆盖的方法时 virtual 是必要的。我问过在覆盖方法时使用这个关键字,而不是声明。 @Miro:我不关注。您通过声明另一个覆盖它的函数来覆盖它。不管怎样,至少我的最后一段回答了你的问题。【参考方案2】:

基类中的virtual 方法将通过层次结构级联,使每个具有相同签名的子类方法也virtual

class Base
public:
  virtual void foo()
;

class Derived1 : public Base
public:
  virtual void foo() // fine, but 'virtual' is no needed
;

class Derived2 : public Base
public:
  void foo() // also fine, implicitly 'virtual'
;

如果仅用于文档目的,我建议您编写 virtual

【讨论】:

【参考方案3】:

当一个函数是虚拟的时,它在整个层次结构中都保持虚拟,无论您是否每次都明确指定它是虚拟的。覆盖方法时,使用 virtual 以更明确 - 没有其他区别:)

class A

    virtual void f() 
    
      /*...*/
    ;
;

class B:public A;

    virtual void f()  //same as just void f()
    
        /*...*/
    ;
;

【讨论】:

【参考方案4】:

Extending on Light Races answer,也许这会帮助一些人看看它在做什么。

struct Base 
public:
    void foo() 
        printf_s("Base::foo\n");
    
;

struct Derived : Base 
    void foo() 
        printf_s("Derived::foo\n");
    
;

struct BaseVirtual 
public:
    virtual void foo() 
        printf_s("BaseVirtual::foo\n");
    
;

struct DerivedVirtual : BaseVirtual 
    virtual void foo() 
        printf_s("DerivedVirtual::foo\n");
     
;

Derived d;
d.foo(); // Outputs: Derived::foo

Base& b = d;
b.foo(); // Outputs: Base::foo

DerivedVirtual d2;
d2.foo(); // Outputs: DerivedVirtual::foo

BaseVirtual& b2 = d2;
b2.foo(); // Outputs: DerivedVirtual::foo

【讨论】:

以上是关于覆盖方法时 virtual 关键字是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 风格:为覆盖方法添加前缀 virtual 关键字

virtual虚函数

C#基础知识:virtual方法,abstract方法,区别

virtual关键字

final 是不是意味着覆盖?

virtual