#cpp
При добавлении спецификатора final мы запрещаем переопределять метод в базовом классе. Тогда зачем нам нужен в базовом классе создавать виртуальный метод, если можно его оставить обычным? Для чего еще используется виртуальный модификатор? class Base { public: virtual void doSomething(int x) final; }; Например вот так: class Base { public: void doSomething(int x); };
Ответы
Ответ 1
Такая комбинация virtual и final будет формально корректной, но фактически бессмысленной. Так что вопрос тут скорее к автору кода: зачем они объявили такой метод? Если задаться целью попритягивать за уши оправдания для такого использования, то возможной причиной может быть желание формально сделать класс полиморфным. (Например, захотелось мне для каких-то моих целей, чтобы dynamic_castработал с указателями типа Base *, а класс Base * как назло у меня не является полиморфным.) Для этого надо создать в нем хотя бы один виртуальный метод, даже если виртуальность этого метода на самом деле "никому больше не нужна". Традиционно в таких ситуациях виртуальным делают деструктор. Но в качестве странноватого альтернативного варианта можно рассмотреть и такую "фиктивную" виртуальность, как в вашем примере. P.S. Не надо называть невиртуальные методы "статическими". Термин статический метод в языке С++ уже зарезервирован и используется для совсем других целей. Ответ 2
Стандартом c++11 спецификатор final определяется как virt-specifier, поэтому он не имеет смысла для невиртуальных методов и генерирует ошибку: marked final, but is not virtual Однако, как правило, final не используется в определении виртуальных методов базового класса. final используется в классах-наследниках, которые переопределяют метод, чтобы предотвратить дальнейшее изменение реализации метода. Поэтому final зачастую используется вместе со спецификатором override.Ответ 3
Спецификатор 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 не несёт смысловой нагрузки, но для наглядности оставил.
Комментариев нет:
Отправить комментарий