C ++ vtable разрешается с виртуальным наследованием - PullRequest
2 голосов
/ 18 июня 2010

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

virtual void doStuff() = 0;

Означает ли это, что разрешение не нужно, потому что есть только один набор функций для выбора?

Простите, если это глупый вопрос - как я уже сказал, я не понимаю, как работает vtables, поэтому я не знаю ничего лучше.

EDIT

Итак, если у меня есть абстрактный класс с двумя отдельными дочерними классами:

    A
   / \
  /   \
 B     C

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

Ответы [ 3 ]

5 голосов
/ 18 июня 2010

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

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

2 голосов
/ 18 июня 2010

Я не знаю, о каком "одном наборе функций" вы говорите.У вас есть два производных класса - B и C - каждый из которых имеет свой собственный набор виртуальных функций.Таким образом, у вас есть как минимум два набора, даже если все функции в A чистые.

Виртуальная диспетчеризация происходит, когда компилятор не знает динамический тип объектаработать с.Например, если у вас есть указатель A *p, он может указывать на объект типа B или типа C.Если компилятор не знает, на какой фактический тип объекта указывает p, он должен будет использовать виртуальную диспетчеризацию для вызова виртуальных функций через p.

PS Нет "виртуального"наследование »в вашем примере.Термин виртуальное наследование в C ++ имеет свое значение.И вы не говорите о виртуальном наследовании здесь.

0 голосов
/ 18 июня 2010

Удар «двойная отправка» происходит только тогда, когда метод является виртуальным. Если производный метод не является виртуальным, производительность не снижается.

...