2012-03-18 2 views
7

В чем разница между этими двумя:Как перегрузка виртуального метода отличается от метода Non-Virtual?

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

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

ответ

6

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

Если имя функции такое же, но подпись в производном классе варьируется от одного в базовом классе, чем не overidding больше, это function Hiding, производный метод класса скрывает метод базового класса.

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

Чтобы применить методы класса Base в рамках класса Derived, вам необходимо добавить
дополнительных using functionName в ваш класс Derived.

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

Хорошо читать:
When to mark a function in C++ as a virtual?

+0

Чтобы перегрузить функцию элемента базового класса в производном классе, вам просто нужно объявление 'using'. – Potatoswatter

+0

@Potatoswatter: Да, вам нужно сделать это в дополнение к простому предоставлению методов, поэтому в этом смысле это больше, чем просто предоставление перегруженных версий. –

+0

Я также пытался сформулировать ответ, но я не мог объяснить различия между созданием функции в базе виртуальной или нет. Вы можете перегружать и то же самое в производном классе (с другой подписью). И я думаю, что это часть вопроса ОП. –

3

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

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

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

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

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

0

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

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

+0

Чтобы сказать, что производный класс ** переопределяет ** функцию базового класса, ключевое слово 'virtual' должно быть задействовано, если нет, его не следует делать. –

+0

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

+0

Извините, что сломал это для вас, но это неверно, если нет «виртуального» ключевого слова, то это не является излишним. –

Смежные вопросы