Когда отмечать функцию в С++ как виртуальную?
Из-за С++-характера статической привязки для методов это влияет на полиморфные вызовы.
Из Википедии:
Хотя накладные расходы, связанные с этим механизмом отправки, низки, могут по-прежнему быть значительными для некоторых областей применения, что язык был предназначен для таргетинга. По этой причине Бьярне Страуструп, дизайнер С++, избранный, чтобы сделать динамическую отправку опциональной и не по умолчанию. Только функции, объявленные с помощью ключевого слова virtual, будут отправляется на основе типа времени выполнения объекта; другие функции будет отправлен на основе статического типа объекта.
Итак, код:
Polygon* p = new Triangle;
p->area();
при условии, что area()
является функцией non-virtual
в классе родителя, которая overridden
в классе Child, код выше вызовет Parent class method
, который разработчик может не ожидать. (благодаря статической привязке, которую я представил)
Итак, если я хочу написать класс, который будет использоваться другими (например, библиотека), должен ли я сделать все мои функции виртуальными для того, чтобы предыдущий код работал как ожидалось?
Ответы
Ответ 1
Простой ответ: если вы планируете переопределить функции своего класса для полиморфизма во время выполнения, вы должны пометить их как virtual
, а не если вы этого не намерены.
Не отмечайте свои функции virtual
только потому, что вы чувствуете, что это придает дополнительную гибкость, скорее подумайте о своем дизайне и целях разоблачения интерфейса. Например: если ваш класс не предназначен для унаследования, тогда ваши виртуальные функции-члены будут вводить в заблуждение. Хорошим примером этого являются контейнеры стандартной библиотеки, которые не предназначены для наследования и, следовательно, у них нет виртуальных деструкторов.
Нет никаких причин, по которым нельзя пометить все ваши функции-члены виртуальными, чтобы указать некоторые штрафы за производительность, тип класса не-POD и т.д., но если вы действительно намереваетесь, чтобы ваш класс был рассчитан на время выполнения, то это это его цель и ее так называемые недостатки.
Ответ 2
Отметьте его виртуальным, если производные классы должны иметь возможность переопределить этот метод. Это так просто.
Ответ 3
Как правило, вы должны отмечать только функцию virtual , если, класс явно предназначен для использования в качестве базового класса, и эта функция предназначена для переопределения. На практике большинство виртуальных функций будут чистыми виртуальными в базовом классе. И за исключением случаев инверсии вызовов, когда вы явно не предоставляете контракт для переопределяющей функции, виртуальные функции должны быть частными (или наиболее защищенными) и завернуты с не виртуальными функциями, обеспечивающими выполнение контракта.
Ответ 4
Что касается производительности памяти, вы получаете таблицу виртуальных указателей, если что-то виртуально, поэтому один из способов взглянуть на нее - "пожалуйста, пожалуйста, все". В противном случае, как говорят другие, отметьте их как виртуальные, если вы хотите, чтобы они были переопределяемыми, так что вызов этого метода в базовом классе означает, что запущены специализированные версии.
Ответ 5
В основном идея; на самом деле, если вы используете родительский класс, я не думаю, что вам нужно переопределить все методы, поэтому просто сделайте их virtual
, если вы думаете, что будете использовать его таким образом.