Является ли ключевое слово "override" просто проверкой для переопределенного виртуального метода?
насколько я понимаю, введение override
ключевое слово в C++11 это не более чем проверка, чтобы убедиться, что функция реализуется это override
ing of a virtual
функция в базовом классе.
- Это что?
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" означает, что это метод предназначена переписать (виртуальный) метод базового класса. Переопределяющий метод должен иметь такую же сигнатуру (по крайней мере, для входных параметров), как и метод, который он намерен переписать.
зачем это нужно? Ну, следующие два распространенных случая ошибок предотвращаются:
один тип опечатки в новом методе. Компилятор, не зная, что он намеревается написать предыдущий метод, просто добавляет его в класс как новый метод. Этот проблема в том, что старый метод все еще существует, новый добавляется просто как перегрузка. В этом случае все вызовы старого метода будут работать так же, как и раньше, без каких-либо изменений в поведении (что было бы самой целью перезаписи).
один забывает объявить метод в суперклассе как "виртуальный", но все еще пытается переписать его в подкласс. Хотя это, по-видимому, будет принято, поведение не будет точно таким, как предполагалось: метод не является виртуальным, поэтому доступ через указатели к суперклассу завершится вызовом старого (суперкласса) метода вместо нового (подкласса) метода.
добавление "override" явно устраняет эту двусмысленность: через это один говорит компилятору, что ожидаются три вещи:
- в суперклассе есть метод с таким же именем
- этот метод в суперклассе объявлен как "виртуальный" (то есть, предназначенный быть переписано)
- метод в суперклассе имеет ту же (входную*) сигнатуру, что и метод в подклассе (метод перезаписи)
Если какой-либо из них является ложным, то сигнализируется об ошибке.
* Примечание: выходной параметр иногда имеет другой, но связанный тип. Читайте о ковариантных и контравариантных преобразованиях, если это интересно.
найден "переопределить " полезно, когда кто-то обновил сигнатуру виртуального метода базового класса, например, добавив необязательный параметр, но забыл обновить сигнатуру метода производного класса. В этом случае методы между базовым и производным классом больше не полиморфные отношения. Без переопределения объявления, это трудно найти этот вид ошибки.
Да, это так. Это проверка, чтобы убедиться, что никто не пытается переопределить и испортить его через неудачную подпись. Вот страница Вики, которая объясняет это подробно и имеет короткий иллюстративный пример:
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final