Чем перегрузка метода Virtual отличается от метода Non-Virtual? - PullRequest
8 голосов
/ 18 марта 2012

В чем разница между этими двумя:

  • Объявление функции базового класса виртуальной и изменение функции производного класса.
  • Перегрузка унаследованной не виртуальной функции.

Когда бы вы использовали один над другим?

Ответы [ 3 ]

6 голосов
/ 18 марта 2012

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

Если имя вашей функции такое же, но подпись в производном классе отличается от подписи в базовом классе, то она больше не переопределяется. Это функция, скрывающая , метод производного класса скрывает Метод базового класса.

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

Чтобы методы класса Base попали в область действия вашего производного класса, вам нужно добавить
дополнительно using functionName к вашему производному классу.

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

Хорошо Читать:
Когда помечать функцию в C ++ как виртуальную?

3 голосов
/ 18 марта 2012

Перегрузка полностью отделена от (ортогональной) виртуальной переопределения .

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

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

Поскольку перегрузка работает с разными сигнатурами, а переопределение работает с одинаковыми сигнатурами, они не мешают друг другу.

Вы можете явно импортировать функции базового класса в производный класс для расширения имени перегруженной функции. Это делается using base_class::overload_name; внутри производного класса.

0 голосов
/ 18 марта 2012

Я полагаю, вы имели в виду переопределение не виртуальных функций, а не перегрузку.Когда вы переопределяете не-виртуальную функцию базового класса в производном классе, то вызов этой функции разрешается и связывается во время компиляции.Это означает, что вызов функции разрешается на основе типа (или указателя), по которому вызывается функция.Если вы вызываете функцию по указателю базового класса, то вызывается версия базового класса, всегда.Если вы используете указатель производного класса, то всегда вызывается производная версия;независимо от фактического объекта, на который он указывает.

В случае, если версия базового класса помечена как виртуальная, тогда разрешение вызова или привязка откладываются для выполнения во время выполнения в зависимости от типа объекта, для которого выполняется вызовсоздается и не зависит от типа указателя, используемого для вызова.Это означает, что вы можете использовать указатель базового класса, чтобы указать на базовый и производный класс объектов, а затем вызвать функцию.В зависимости от типа объекта, на который указывает указатель, вызывается соответствующая версия функции.Это означает, что если мой указатель указывает на объект базового класса, то вызывается версия базового класса.Если указатель указывает на объект производного типа, вызывается производная версия.

...