Виртуальная? переопределить? или оба? С++

в последние недели что-то подталкивает мой мозг к виртуальному и переопределению. Я узнал, что когда вы наследуете виртуальную функцию, вам нужно добавить virtual, чтобы компилятор знал, что нужно искать правильную функцию. Впоследствии я узнал также, что в С++ 11 есть новое ключевое слово - переопределить. Теперь я немного смущен; Нужно ли мне использовать как виртуальные, так и переопределяющие ключевые слова в моей программе, или лучше использовать только один из них?

Чтобы объяснить себя - примеры кода, что я имею в виду:

class Base
{
public:
    virtual void print() const = 0;
    virtual void printthat() const = 0;
    virtual void printit() const = 0;
};

class inhert : public Base
{
public:
    // only virtual keyword for overriding.
    virtual void print() const {}

    // only override keyword for overriding.
    void printthat() const override {}

    // using both virtual and override keywords for overriding.
    virtual void printit() const override {}
};

Каков наилучший метод?

Ответ 1

Когда вы переопределяете функцию, вам технически не нужно писать либо virtual, либо override.

В исходном объявлении базового класса требуется ключевое слово virtual, чтобы пометить его как виртуальное.

В производном классе функция является виртуальной с помощью того же типа, что и функция базового класса.

Однако override может помочь избежать ошибок, вызвав ошибку компиляции, когда предполагаемое переопределение не является технически переопределяющим. Например. что тип функции не совсем похож на функцию базового класса. Или что поддержание базового класса изменяет тип функции, например. добавление аргумента по умолчанию.

Таким же образом ключевое слово virtual в производном классе может сделать такую ​​ошибку более тонкой, гарантируя, что функция все еще является виртуальной в следующих производных классах.

Итак, общий совет:

  • Используйте virtual для объявления функции базового класса.
    Это технически необходимо.

  • Используйте override (только) для переопределения производного класса.
    Это помогает в обслуживании.

Пример:

struct Base { virtual void foo() {} };
struct Derived: Base { void foo() override {} };

Примечания:
¹ С++ поддерживает ковариантный необработанный указатель и исходные ссылочные результаты. С ковариацией тип переопределения не совсем то же самое. Он имеет совместимый тип.