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

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

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

Это что?

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Изменить (попытка немного улучшить ответ):

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

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

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

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

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

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

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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

Проект стандарта С++ 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
}

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

поэтому я считаю, что предотвращение ошибок программиста на самом деле является единственным эффектом.