Я видел код в производном классе недавно, в который программист поместил virtual
перед переопределенными функциями. Действительно ли это распространено? Я думал, что это было очень нечетно, и это отчасти застало меня врасплох.
Править: Я не спрашиваю, что виртуальный делает, я спрашиваю, почему кто-то поместил бы виртуальный в производный класс, который уже переопределяет виртуальные функции в его базовом классе.
EX:
class B {
public:
virtual void foo();
....
};
class D : public B {
public:
virtual void foo(); // could have just put void foo();
...
};
virtual
необходим для переопределяемых функций на самом высоком (наименее производном) уровне. На более низких (более производных) уровнях он необязателен, но безвреден. Это полезно для самодокументирования кода.
Ничего странного в этом не вижу. Во многих случаях (если не в большинстве случаев) программисты создают объявление замещающей функции в производном классе, копируя ее из базового класса. Нет смысла тратить дополнительные усилия на удаление вручную избыточного виртуального спецификатора
. Более того, явный virtual
упрощает просмотр того, какие функции являются виртуальными.
Это очень часто. Его рекомендуют многие руководства по стилю, например Google . Цель - улучшить читаемость кода.
Другой способ улучшить читабельность - использовать что-то вроде этого:
class B {
public:
virtual void foo();
....
};
class D : public B {
public:
/*override*/ void foo();
...
};
Предположу, что вы знаете назначение ключевого слова virtual, но задаетесь вопросом, почему оно вдруг появляется в подтипе. Если я ошибаюсь, мой ответ, вероятно, не будет иметь большого смысла, но подойдет любая ссылка на C++.
Совершенно законно помещать virtual в производный класс. В результате, если у вас есть ссылка или указатель на этот класс или любой из его подклассов, вызовы этой функции будут связаны динамически на основе типа времени выполнения.
Однако, хотя это и законно, не считается хорошим дизайном иметь невиртуальный метод в базовом классе и виртуальный в переопределенной версии.
Одна из причин заключается в том, что вы можете иметь экземпляр производного класса, а затем один указатель на базовый класс и один указатель на производный, и оба указателя будут нацелены на этот экземпляр. Вызов одной и той же функции для каждого указателя будет иметь разный результат, поскольку вызов указателя, объявленного в базовом классе, будет нацелен на определение в базовом классе.
Это поможет, если и в будущем. Если кто-то хочет получить класс D и иметь виртуальные функции, то его легко понять