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


227

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

Это оно?


50
Да.⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣
Р. Мартиньо Фернандес

13
Это не двойная проверка, хотя. Это единственная проверка.
Никос К.

13
эй, переопределение не является ключевым словом, это своего рода грамматический сахар. int override = 42; // ОК
KAlO2

2
Это дополнительно улучшает читабельность, объясняя, что объявленная функция переопределена;)
mots_g

5
Итак ... Когда C ++ 11 станет достаточно стандартным, чтобы они начали преподавать такие вещи на моем местном 4-м курсе? Когда они узнают ?!
Cinch

Ответы:


264

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

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

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

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


74
+1: Хотя, к сожалению, это немного красная сельдь, когда люди предполагают, что новая overrideфункция «исправляет» это; Вы должны помнить, чтобы использовать его, так же, как вы должны были помнить, чтобы написать const;)
Гонки Легкости на Орбите

Я просто понял, что explicitопределения классов не попали в C ++ 11. Да.
aschepler

1
@aschepler А что будет explicitделать определение класса? Никогда не слышал об этом вообще.
Кристиан Рау

18
@LightnessRacesinOrbit: Да, это не доказательство; однако, помнить общее правило (безумно писать, overrideкогда кто-то намеревается это сделать) более вероятно, чем запоминание угловых случаев, т. е. нет универсальности в копировании функций различных прототипов, только нарушения, такие как отсутствие constили запись charвместо intи т. д.
legends2k

1
@Light, лучший вариант использования overrideспецификатора упоминается в этом ответе , который является скорее футуристическим, чем немедленным. Ответ предполагает , что, сохранить overrideс virtualметодом. В будущем, когда кто-то по ошибке меняет подпись, его полезность начинает
действовать

36

Цитата из Википедии:

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

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

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

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

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

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

  2. забывают объявить метод в суперклассе как «виртуальный», но все же пытаются переписать его в подклассе. Хотя это, очевидно, будет принято, поведение будет не совсем таким, как предполагалось: метод не является виртуальным, поэтому доступ через указатели к суперклассу закончится вызовом старого (суперкласс ') метода вместо нового (подкласс') метода.

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

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

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

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


31

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


1
+1. Хотя overrideэто отличный способ для выявления таких проблем, хорошее тестирование юнит-тестов также должно помочь.
Разочарован

1
Именно поэтому я так взволнован этим новым спецификатором. Единственная проблема заключается в том, что эта функция уже должна применяться, чтобы предотвратить ошибки, вызванные изменениями в базовых классах. ;-)
Вольф

5

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

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


2

Проект стандарта C ++ 17

После просмотра всех overrideобращений к черновику стандарта C ++ 17 N4659 единственная ссылка, которую я могу найти на overrideидентификатор:

5 Если виртуальная функция помечена с помощью переопределения virt-спецификатора и не переопределяет функцию-член базового класса, программа имеет неверный формат. [ Пример:

struct B {
  virtual void f(int);
};

struct D : B {
  virtual void f(long) override; // error: wrong signature overriding B::f
  virtual void f(int) override;  // OK
}

- конец примера]

поэтому я думаю, что, возможно, взорвать неправильные программы на самом деле единственный эффект.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.