Насколько я понимаю, введение ключевого слова override
в С++ 11 является не чем иным, как проверкой, чтобы убедиться, что реализуемая функция - это override
ing функции virtual
в базе класс.
Это что?
Насколько я понимаю, введение ключевого слова override
в С++ 11 является не чем иным, как проверкой, чтобы убедиться, что реализуемая функция - это override
ing функции virtual
в базе класс.
Это что?
Это действительно идея. Дело в том, что вы явно говорите о том, что вы имеете в виду, чтобы можно было диагностировать иную тихую ошибку:
struct Base
{
virtual int foo() const;
};
struct Derived : Base
{
virtual int foo() // whoops!
{
// ...
}
};
Вышеприведенный код компилируется, но это не то, что вы могли иметь в виду (обратите внимание на отсутствующий const
). Если вы сказали вместо этого virtual int foo() override
, то вы получите ошибку компилятора, что ваша функция на самом деле ничего не отменяет.
Цитата из Википедии:
Специальный идентификатор переопределения означает, что компилятор проверит базовый класс (es), чтобы увидеть, есть ли виртуальная функция с этой точной подписью. И если этого не произойдет, компилятор выйдет из строя.
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Изменить (попытка немного улучшить ответ):
Объявление метода как "переопределения" означает, что этот метод предназначен для перезаписи (виртуального) метода в базовом классе. Метод переопределения должен иметь такую же подпись (по крайней мере для входных параметров) как метод, который он намеревается переписать.
Почему это необходимо? Ну, предотвращаются следующие два распространенных случая ошибок:
один тип ошибок в новом методе. Компилятор, не подозревая, что он намеревается написать предыдущий метод, просто добавляет его в класс как новый метод. Проблема в том, что старый метод все еще существует, новый добавляется как перегрузка. В этом случае все обращения к старому методу будут действовать так же, как и раньше, без каких-либо изменений в поведении (что было бы самой целью перезаписи).
один забывает объявить метод в суперклассе как "виртуальный", но все же пытается перезаписать его в подклассе. Хотя это, по-видимому, будет принято, поведение будет не таким, как предполагалось: метод не является виртуальным, поэтому доступ через указатели к суперклассу приведет к вызову старого (суперкласса) метода вместо нового (подкласса).
Добавление "переопределения" явно устраняет это: через это сообщается компилятору, что ожидаются три вещи:
Если какое-либо из них является ложным, то сигнализируется ошибка.
* note: выходной параметр иногда имеет разные, но родственный тип. Прочитайте о ковариантных и контравариантных преобразованиях, если они заинтересованы.
Найдено " переопределить" полезно, когда кто-то обновил подпись виртуального метода базового класса, например добавление необязательного параметра, но забыл обновить сигнатуру метода производного класса. В этом случае методы между базой и производным классом уже не являются полиморфными. Без объявления переопределения трудно найти такую ошибку.
Да, это так. Это проверка, чтобы убедиться, что вы не пытаетесь переопределить и испортить ее через поврежденную подпись. Здесь страница Wiki, которая подробно объясняет это и имеет короткий иллюстративный пример:
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Проект стандарта С++ 17
После просмотра всех совпадений override
в черновике стандарта С++ 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 }
- конец примера]
поэтому я считаю, что предотвращение ошибок программиста на самом деле является единственным эффектом.