Какой самый краткий, но точный способ описать, что такое виртуальная функция в C ++? - PullRequest
6 голосов
/ 20 марта 2011

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

Если я проконсультируюсь с Википедией, я увижу определение виртуальной функции:

"В объектно-ориентированном программировании виртуальная функция или виртуальный метод - это функция или метод, поведение которых может быть переопределено в классе наследования функцией с такой же сигнатурой"

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

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

Полагаю, меня смущает вопрос о том, является ли описание "указателя" виртуальных функций чем-то фундаментальным для их определения, или просто случайным для их реализации в C ++.

Ответы [ 11 ]

0 голосов
/ 20 марта 2011

Предположим, что бета-версия является подклассом Alpha и может создать новую область метода () или добавить виртуальную область.

Нет разницы, если вы говорите сБета-указатель.Но если вы говорите с Альфой *, которая указывает на Бета-объект, вы получите метод Альфы.Если вы не объявите функцию как виртуальную.

Подкласс бета-версии имеет свою таблицу диспетчеризации функций, которая является копией таблицы Альфы, но с дополнительными бета-методами в конце.Если бета-версия просто переопределяет метод, она попадает в раздел бета-таблицы диспетчеризации, поэтому ссылки на альфа * не увидят новый метод.Но если новый метод является виртуальным, он перейдет в раздел Alpha таблицы классов Beta.

Более конкретно, скажем, у вас есть подкласс Circle Shape.Допустим, у вас есть указатель на объект Shape, x, который является экземпляром Circle.x-> area () будет видеть только ту часть таблицы функций, которая относится к Shape.Если Circle выполняет функцию виртуальной области, она появится в разделе Shape таблицы.Если Circle просто переопределяет область, то метод area будет помещен в часть Circle таблицы, и Shape * x не увидит новую функцию.

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

...