Является ли ключевое слово "override" просто проверкой для переопределенного виртуального метода?


насколько я понимаю, введение override ключевое слово в C++11 это не более чем проверка, чтобы убедиться, что функция реализуется это overrideing of a virtual функция в базовом классе.

- Это что?

4 173

4 ответа:

Это действительно идея. Дело в том, что вы явно говорите о том, что вы имеете в виду, так что в противном случае можно диагностировать молчаливую ошибку:

struct Base
{
    virtual int foo() const;
};

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};

приведенный выше код компилируется, но это не то, что вы могли иметь в виду (обратите внимание на отсутствие const). Если бы ты сказал вместо этого:virtual int foo() override, то вы получите ошибку компилятора, что ваша функция на самом деле не переопределяя ничего.

Википедии цитата:

переопределение специального идентификатора означает, что компилятор будет проверять базовый класс (ы), чтобы увидеть, есть ли виртуальная функция с этой точной сигнатурой. А если нет, то компилятор выдаст ошибку.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

редактировать (пытаясь немного улучшить ответ):

объявление метода как "override" означает, что это метод предназначена переписать (виртуальный) метод базового класса. Переопределяющий метод должен иметь такую же сигнатуру (по крайней мере, для входных параметров), как и метод, который он намерен переписать.

зачем это нужно? Ну, следующие два распространенных случая ошибок предотвращаются:

  1. один тип опечатки в новом методе. Компилятор, не зная, что он намеревается написать предыдущий метод, просто добавляет его в класс как новый метод. Этот проблема в том, что старый метод все еще существует, новый добавляется просто как перегрузка. В этом случае все вызовы старого метода будут работать так же, как и раньше, без каких-либо изменений в поведении (что было бы самой целью перезаписи).

  2. один забывает объявить метод в суперклассе как "виртуальный", но все еще пытается переписать его в подкласс. Хотя это, по-видимому, будет принято, поведение не будет точно таким, как предполагалось: метод не является виртуальным, поэтому доступ через указатели к суперклассу завершится вызовом старого (суперкласса) метода вместо нового (подкласса) метода.

добавление "override" явно устраняет эту двусмысленность: через это один говорит компилятору, что ожидаются три вещи:

  1. в суперклассе есть метод с таким же именем
  2. этот метод в суперклассе объявлен как "виртуальный" (то есть, предназначенный быть переписано)
  3. метод в суперклассе имеет ту же (входную*) сигнатуру, что и метод в подклассе (метод перезаписи)

Если какой-либо из них является ложным, то сигнализируется об ошибке.

* Примечание: выходной параметр иногда имеет другой, но связанный тип. Читайте о ковариантных и контравариантных преобразованиях, если это интересно.

найден "переопределить " полезно, когда кто-то обновил сигнатуру виртуального метода базового класса, например, добавив необязательный параметр, но забыл обновить сигнатуру метода производного класса. В этом случае методы между базовым и производным классом больше не полиморфные отношения. Без переопределения объявления, это трудно найти этот вид ошибки.

Да, это так. Это проверка, чтобы убедиться, что никто не пытается переопределить и испортить его через неудачную подпись. Вот страница Вики, которая объясняет это подробно и имеет короткий иллюстративный пример:

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final