Страницы

Поиск по вопросам

пятница, 13 декабря 2019 г.

Спецификатор final для функции

#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 не несёт смысловой нагрузки, но для наглядности оставил.

Комментариев нет:

Отправить комментарий