Для чего нужно ключевое слово override в C++?

«Для чего нужно ключевое слово override в C++?» — вопрос из категории ООП, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово override (начиная с C++11) явно указывает, что метод переопределяет виртуальный метод базового класса. Это защита от ошибок и улучшение читаемости кода.

Проблема без override:

class Base {
public:
    virtual void draw() const {
        std::cout << "Base drawn";
    }
    virtual void serialize(int version) {
        std::cout << "Base serializen";
    }
};

class Derived : public Base {
public:
    // ОПЕЧАТКА: draw вместо Draw - НЕ переопределение!
    void Draw() const {  // Без override компилятор пропустит
        std::cout << "Derived drawn";
    }

    // ИЗМЕНЕНИЕ СИГНАТУРЫ: забыли const - НЕ переопределение!
    void draw() {  // Без override компилятор пропустит
        std::cout << "Derived draw (non-const)n";
    }
};

Решение с override:

class DerivedSafe : public Base {
public:
    void Draw() const override {  // ОШИБКА КОМПИЛЯЦИИ: нет метода Draw в Base
        std::cout << "Derived drawn";
    }

    void draw() override {  // ОШИБКА КОМПИЛЯЦИИ: сигнатура не совпадает (нет const)
        std::cout << "Derived drawn";
    }

    // Правильные переопределения:
    void draw() const override {  // OK
        std::cout << "Derived drawn";
    }

    void serialize(int version) override {  // OK
        std::cout << "Derived serialize v" << version << "n";
    }
};

Преимущества использования override:

  1. Обнаружение ошибок на этапе компиляции - опечатки, изменение сигнатур
  2. Улучшение читаемости - явно видно, какие методы переопределяют базовые
  3. Поддержка рефакторинга - если изменить метод в базовом классе, компилятор покажет все места, где нужно обновить переопределения

Связанное ключевое слово final:

class Base {
public:
    virtual void cannotOverride() final {}
};

class Derived : public Base {
public:
    void cannotOverride() override {} // ОШИБКА: метод final в Base
};