Чи ключове слово "переосмислити" - це лише перевірка перекритого віртуального методу?


226

Наскільки я розумію, введення overrideключового слова в C ++ 11 є не більше ніж перевірка , щоб переконатися , що функція реалізується є overrideІНГ з virtualфункції в базовому класі.

Це все?


50
Так.⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣
Р. Мартіньо Фернандес

13
Але це не подвійна перевірка. Це єдина перевірка.
Нікос С.

13
ей, переоцінка НЕ ​​ключове слово, це свого роду граматичний цукор. int override = 42; // ОК
KAlO2

2
Це також покращує читабельність, пояснюючи, що задекларована функція є відміненою;)
mots_g

5
Отже, е-е ... Коли C ++ 11 стане достатньо стандартним, що вони почнуть вчити такі речі на моєму місцевому 4-річному курсі? Коли вони дізнаються ?!
Cinch

Відповіді:


263

Це справді ідея. Справа в тому, що ви чітко розумієте, що ви маєте на увазі, щоб інакше мовчати помилку:

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методом. Надалі, коли хтось помилково змінює підпис, його корисність починає.
iammilind

35

Цитата у Вікіпедії:

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

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

Редагувати (намагаючись трохи покращити відповідь):

Оголошення методу "переосмислення" означає, що цей метод призначений для перезапису (віртуального) методу на базовий клас. Метод переосмислення повинен мати такий самий підпис (принаймні для вхідних параметрів), як метод, який він має намір переписати.

Чому це потрібно? Ну, запобігаються наступні два поширених випадки помилок:

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

  2. можна забути оголосити метод у надкласі як "віртуальний", але все ж намагається переписати його в підклас. Хоча це буде, очевидно, прийнято, поведінка не буде точно так, як задумано: метод не є віртуальним, тому доступ через покажчики на надклас закінчується викликом старого (надкласового) методу замість нового (підкласу) методу.

Додавання "переопрацювання" очевидно роз'єднує це: через це, потрібно сказати компілятору, що три речі очікують:

  1. є метод з такою ж назвою в суперкласі
  2. цей метод у надкласі оголошується як "віртуальний" (це означає, призначений для переписування)
  3. метод у надкласі має такий самий (вхідний *) підпис, що і метод у підкласі (метод переписування)

Якщо будь-яке з них невірно, то сигналізується про помилку.

* Примітка: вихідний параметр іноді відрізняється, але пов'язаний тип. Читайте про коваріантні та противаріантні перетворення, якщо вас цікавить.


31

Знайдено " переосмислити " корисно, коли хтось оновив підпис віртуального методу базового класу, наприклад додавання необов'язкового параметра, але забув оновити підпис методу отриманого класу. У цьому випадку методи між базовим та похідним класом вже не є поліморфним відношенням. Без декларації про переоцінку важко з’ясувати подібний помилку.


1
+1. Хоча, хоча overrideце чудовий спосіб виявити подібні проблеми, гарне покриття тестових одиниць також повинно допомогти.
Розчарований

1
Саме тому я так схвильований цим новим специфікатором. Єдина проблема полягає в тому, що ця функція повинна бути застосована для запобігання помилок, викликаних змінами в базових класах. ;-)
Вовк


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.