Когда отмечать функцию в С++ как виртуальную?

Из-за С++-характера статической привязки для методов это влияет на полиморфные вызовы.

Из Википедии:

Хотя накладные расходы, связанные с этим механизмом отправки, низки, могут по-прежнему быть значительными для некоторых областей применения, что язык был предназначен для таргетинга. По этой причине Бьярне Страуструп, дизайнер С++, избранный, чтобы сделать динамическую отправку опциональной и не по умолчанию. Только функции, объявленные с помощью ключевого слова 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, если вы думаете, что будете использовать его таким образом.