Задний план
Я только что наткнулся на вариант использования override
спецификатора, который , насколько я могу судить, кажется избыточным, а также без какого-либо особого семантического значения, но, возможно, я что-то упускаю, отсюда и этот вопрос. Прежде чем продолжить, я должен указать, что я пытался найти ответ на него здесь, на SO, но ближайшими, которые я получил, были следующие потоки, на самом деле не отвечающие на мой запрос (возможно, кто-то может указать на вопросы и ответы, которые на самом деле уже отвечают на мои вопрос).
- Объяснение C ++ Virtual / Pure Virtual
- С ++ переопределяет чистый виртуальный метод чистым виртуальным методом
Вопрос
Рассмотрим следующий абстрактный класс:
struct Abstract {
virtual ~Abstract() {};
virtual void foo() = 0;
};
Есть ли какая-либо причина использовать спецификатор override
при реализации foo()
в неабстрактном классе, производном непосредственно от Abstract
(как в DerivedB
ниже)? То есть, когда реализация foo()
уже требуется, чтобы производный класс был неабстрактным (и на самом деле ничего не переопределял)?
/* "common" derived class implementation, in my personal experience
(include virtual keyword for semantics) */
struct DerivedA : public Abstract {
virtual void foo() { std::cout << "A foo" << std::endl; }
};
/* is there any reason for having the override specifier here? */
struct DerivedB : public Abstract {
virtual void foo() override { std::cout << "B foo" << std::endl; }
};
4 ответа
Я не большой поклонник override
, но, если предположить, что это что-то, что вы сочтете полезным в целом, тогда да, добавление override
к виртуальной функции, которая заменяет чистые виртуальные функции, полезно. Рассмотрим этот довольно надуманный пример:
struct Base {
virtual void f() = 0;
};
struct Derived : Base {
virtual void f();
virtual void f(int);
};
Теперь предположим, что сопровождающий Base
(возможно, даже ваше будущее) изменяет Base
, чтобы он выглядел так:
struct Base {
virtual void f(int) = 0;
};
Теперь поведение Derived
незаметно изменилось. С override
компилятор сообщит об ошибке.
Что касается почему хорошо, если были объявлены все переопределенные методы override
:…
class Abstract {
virtual void foo() { ...}
};
class Derived : public Abstract {
void foo() override { ... }
};
Теперь, если подпись Abstract::foo
изменится, скажем,
class Abstract {
virtual void foo(int bar) { ...}
};
Компилятор выдаст ошибку в Derived::foo
, поскольку он больше не переопределяет функцию Abstract
, чего не было бы без квалификатора override
. Это поможет вам лучше поддерживать ваш код. Однако в вашем конкретном случае (т.е. с чистыми виртуальными объявлениями) также будет выдана ошибка. Так что использование override
в основном считается "хорошей практикой", я думаю. Подробнее по этой теме: http://en.cppreference.com/w/cpp/language/ переопределить
Основным преимуществом override
здесь будет облегчение сопровождения. Рассмотрим ниже:
class Foo
{
public:
virtual void foo() = 0;
};
class Derived : public Foo
{
public:
//....
virtual void foo(double x) override
{
//This throws error
}
};
Как вы можете видеть выше, компилятор выдаст ошибку, если вы скомпилируете вышеуказанное. Что может случиться, так это то, что компилятор будет жаловаться на то, что функция не имеет такой же подписи. Без ключевого слова override
результат был бы другим.
В случае чисто виртуальных функций и компиляций нет. Вы все равно получите сообщение об ошибке (кроме как в примере от Пита)
Но сообщение об ошибке может быть более читаемым, если вы получите ошибку типа « ваша функция ничего не отменяет » по сравнению с более поздним « не может создать экземпляр абстрактного класса »
Еще одно преимущество - при чтении объявления вы знаете, что это производный метод от базового класса.
Также рекомендуется просто привыкнуть объявлять все переопределенные методы с помощью override
. Так зачем здесь иметь значение и иметь противоречивый стиль.
Что касается почему хорошо, если были объявлены все переопределенные методы override
:
Что касается почему хорошо, если были объявлены все переопределенные методы {{X0}}:…
class A
{
virtual void Foo();
};
class B: public A
{
virtual void Foo() override;
};
Что касается почему хорошо, если были объявлены все переопределенные методы Foo
:…
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.