Подтвердить что ты не робот

Есть ли смысл использовать `override` при переопределении чистой виртуальной функции?

Например:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function() override;
};

Из того, что я читал, ключевое слово override используется, чтобы убедиться, что у нас есть правильная подпись в функции, которую мы переопределяем, и это, по-видимому, единственное ее использование.

Однако в случае чистой виртуальной функции компилятор выдает ошибку, если мы использовали неправильную подпись в классе Derived (или базовый класс, в зависимости от того, как вы видите вещи). Итак, есть ли смысл добавить override в конец объявления Derived::my_function()?

4b9b3361

Ответ 1

Однако в случае чистой виртуальной функции компилятор выдает ошибку, если мы использовали неправильную подпись в классе Derived

Нет, это компилируется:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function(int);
//                 ^^^ mistake!
};

Пока это не так:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function(int) override;
};

error: void Derived::my_function(int) отмечен override, но не переопределяет


Ошибка, о которой вы говорите, возникает только тогда, когда экземпляр Derived - override позволяет вам поймать ошибку раньше и делает определение Derived более четким/читаемым.

Ответ 2

Да, рекомендуется использовать ключевое слово override последовательно как защитную практику.

Рассмотрим редизайн, когда автор Base решает, что my_function больше не будет чистым виртуальным, а также что он должен принять новый параметр. С override на месте компилятор поймает эту проблему; без override ваш класс Derived будет продолжать компилироваться.

Ответ 3

Да!

Улучшает ясность кода: override предотвращает двусмысленность и передает смысл переопределения метода базового класса.

Предотвращает возможное непреднамеренное использование:  В будущем, если подпись метода изменения базового класса (здесь virtual), он принудительно меняет класс. (с ошибкой компилятора). В противном случае (без ключа override) его можно считать method overload, который не предназначен.

Ответ 4

Обычно не беспокоит override, просто перемещает ошибку. Я нахожу место, где вы получаете ошибку лучше - в точке, где вы определяете метод, который не может переопределить, а не когда вы создаете экземпляр класса.

Но для этого существует способ защиты от ошибки времени выполнения.

struct Base {
  virtual void foo(int x = 0) = 0;

  void foo(double d) {
      foo( (int)d );
  }
};
inline void Base::foo(int x) { std::cout << "Default foo(" << x << ")\n"; }

struct Derived:Base {
  using Base::foo;
  virtual void foo() { // oops, no int!
    std::cout << "Derived::foo()\n";
    Base::foo();
  }
};
struct Derived2:Derived {
  virtual void foo(int x=0) override {
    std::cout << "Derived2::foo()\n";
    Derived::foo(x);
  }
};

здесь мы намерены для каждого foo вызвать его родительский foo. Но поскольку Derived::foo не переопределяет ту же подпись, что и Base::foo, она не вызывается.

Добавьте override после foo() в Derived, и мы получим ошибку времени компиляции.

И да, я реализовал чистую виртуальную функцию Base::foo.