Когда помечать функцию в C ++ как виртуальную? - PullRequest
11 голосов
/ 28 ноября 2011

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

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

Хотя накладные расходы, связанные с этим механизмом диспетчеризации, низкие, онможет по-прежнему иметь значение для некоторых областей применения, для которых предназначен язык.По этой причине Бьярн Страуструп, дизайнер C ++, решил сделать динамическую диспетчеризацию необязательной и нестандартной.Только функции, объявленные с виртуальным ключевым словом, будут отправлены на основе типа времени выполнения объекта;другие функции будут отправляться на основе статического типа объекта.

Таким образом, код:

Polygon* p = new Triangle;
p->area();

при условии, что area() является non-virtual функцией в родительском классе, который являетсяoverridden в классе Child, приведенный выше код будет вызывать Parent's class method, что может не ожидаться разработчиком.(благодаря введенной статической привязке)

Итак, если я хочу написать класс, который будет использоваться другими (например, библиотекой), я должен сделать все свои функции виртуальными длятакой предыдущий код для запуска, как ожидалось?

Ответы [ 5 ]

23 голосов
/ 28 ноября 2011

Простой ответ: если вы хотите, чтобы функции вашего класса были переопределены для полиморфизма во время выполнения, вы должны пометить их как virtual, а не, если вы не собираетесь этого делать.

Не отмечайтефункции virtual только потому, что вы чувствуете, что это придает дополнительную гибкость, лучше подумайте о своем дизайне и цели раскрытия интерфейса.Например: если ваш класс не предназначен для наследования, то создание виртуальных функций-членов будет вводить в заблуждение.Хорошим примером этого являются контейнеры стандартной библиотеки, которые не предназначены для наследования и, следовательно, у них нет виртуальных деструкторов.

Нет причин, по которым не следует отмечать все функции-члены как виртуальные, чтобы заключить их в кавычкинекоторые потери производительности, не относящиеся к типу POD и т. д., но если вы действительно хотите, чтобы ваш класс был предназначен для переопределения во время выполнения, то это является его целью, а также устраняет и устраняет так называемые недостатки.

3 голосов
/ 28 ноября 2011

Отметьте его как виртуальный, если производные классы должны иметь возможность переопределять этот метод. Это так просто.

2 голосов
/ 28 ноября 2011

Как правило, вы должны пометить функцию как виртуальную только если , класс явно предназначен для использования в качестве базового класса, и эта функция предназначена для переопределения. На практике большинство виртуальных функций будут чисто виртуальными в базовом классе. И за исключением случаев инверсии вызовов, когда вы явно не предоставляете контракт для переопределяющей функции, виртуальные функции должны быть частными (или максимально защищенными) и обернуты не виртуальными функциями, обеспечивающими выполнение контракта.

1 голос
/ 28 ноября 2011

С точки зрения производительности памяти, вы получаете таблицу виртуальных указателей, если что-либо является виртуальным, поэтому один из способов посмотреть на это - «пожалуйста, один, пожалуйста, все». В противном случае, как говорят другие, пометьте их как виртуальные, если вы хотите, чтобы они были перезаписываемыми, так что вызов этого метода в базовом классе означает, что запускаются специализированные версии.

0 голосов
/ 28 ноября 2011

Это в основном идея;на самом деле, если вы используете родительский класс, я не думаю, что вам нужно переопределять все методы, поэтому просто сделайте их virtual, если вы думаете, что будете использовать их таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...