Что означает ключевое слово Virtual при переопределении метода?

Что означает слово виртуальный do при переопределении метода? Я не использую его и все работает нормально.

каждый ли компилятор ведет себя одинаково в этом отношении?

должен ли я использовать его или нет?

3 ответов


вы не можете переопределить функцию-член без него.

вы можете только скрыть один.

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 - ваш объект является полиморфным.

(кроме есть использовать ссылки или указатели для этого, из-за нарезки проблема.)


  • Derived::foo не нужно повторять virtual ключевое слово, потому что Base::foo уже использовал его. Это гарантировано стандартом, и вы можете положиться на него. Однако некоторые считают лучше держать это в себе для ясности.

A 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 хотя, если только для целей документации.


когда функция виртуальна, она остается виртуальной во всей иерархии, независимо от того, указываете ли вы явно каждый раз, когда она виртуальна. При переопределении метода используйте virtual, чтобы быть более явным - никакой другой разницы:)

class A
{
    virtual void f() 
    {
      /*...*/
    };
};

class B:public A;
{
    virtual void f()  //same as just void f()
    {
        /*...*/
    };
};