При добавлении спецификатора final мы запрещаем переопределять метод в базовом классе. Тогда зачем нам нужен в базовом классе создавать виртуальный метод, если можно его оставить обычным? Для чего еще используется виртуальный модификатор?
class Base
{
public:
virtual void doSomething(int x) final;
};
Например вот так:
class Base
{
public:
void doSomething(int x);
};
Такая комбинация virtual и final будет формально корректной, но фактически бессмысленной. Так что вопрос тут скорее к автору кода: зачем они объявили такой метод?
Если задаться целью попритягивать за уши оправдания для такого использования, то возможной причиной может быть желание формально сделать класс полиморфным. (Например, захотелось мне для каких-то моих целей, чтобы dynamic_cast<void *> работал с указателями типа Base *, а класс Base * как назло у меня не является полиморфным.) Для этого надо создать в нем хотя бы один виртуальный метод, даже если виртуальность этого метода на самом деле "никому больше не нужна". Традиционно в таких ситуациях виртуальным делают деструктор. Но в качестве странноватого альтернативного варианта можно рассмотреть и такую "фиктивную" виртуальность, как в вашем примере.
P.S. Не надо называть невиртуальные методы "статическими". Термин статический метод в языке С++ уже зарезервирован и используется для совсем других целей.
Стандартом c++11 спецификатор final определяется как virt-specifier, поэтому он не имеет смысла для невиртуальных методов и генерирует ошибку:
marked final, but is not virtual
Однако, как правило, final не используется в определении виртуальных методов базового класса.
final используется в классах-наследниках, которые переопределяют метод, чтобы предотвратить дальнейшее изменение реализации метода.
Поэтому final зачастую используется вместе со спецификатором override.
Спецификатор final обычно не используют в базовом классе (смотри ответ vp_arth).
Данный модификатор используется, чтобы запретить переопределение виртуальной функции в классе-наследнике, поэтому обычно используется при наследовании более чем на 2 уровня.
struct A {
virtual void foo() { std::cout << "I'm A!\n"; }
};
struct B : A {
virtual void foo() override final { std::cout << "I'm B!\n"; }
};
struct C : B {
virtual void foo() override { std::cout << "I'm C!\n"; } // <- запрещено, ошибка времени компиляции
};
P.S. В наследниках ключевое слово virtual не несёт смысловой нагрузки, но для наглядности оставил.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости