Множественное наследование, виртуальные функции и виртуальная таблица в C++
Я знаю, что поиск виртуальных функций в vtable намного медленнее, чем прямой вызов функций, поскольку базовый класс должен искать в vtable, чтобы получить производную функцию. Я бродил, было бы еще медленнее, если бы было больше производных слоев классов. В основном мой вопрос заключается в следующем:
Вызывает ли виртуальная функция Base -> Derived (1 уровень наследования) более быстрый вызов, чем вызов виртуальной функции Base -> Derived1 -> Derived2 -> Derived3 -> DerivedEtc (множественные уровни)?
1 ответ
Нет разницы в производительности поиска с одним косвенным путем, чтобы найти виртуальную функцию, которая будет вызываться в случае класса, полученного из двухуровневого наследования, а не из класса, наследуемого из 40 уровней.
Причина в следующем: каждый класс содержит указатель на виртуальную таблицу, которая используется для определения, какая функция должна быть вызвана для этого конкретного объекта:
class Base
{
public:
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
Приведенный выше код генерирует три виртуальные таблицы: одну для объектов класса Base
один для предметов класса D1
и один для объектов класса D2
,
Важным моментом здесь является то, что вам не нужно проходить все виртуальные таблицы с нуля, чтобы найти, какую функцию вызывать для конкретного объекта:
на диаграмме выше вы просто
- Следовать
vptr
для вашего объекта (одно направление) - Назовите адрес интересующей вас функции
Современные компиляторы могут оптимизировать этот процесс в двух пунктах, которые я перечислил выше, и, за исключением некоторых особых случаев, это не окажет заметного влияния на производительность.
Кредиты: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/
Дополнительно: как отметил dyp, "медленное выполнение" виртуальных функций обычно относится к тому факту, что эти функции не могут быть встроены из-за косвенной зависимости vtable. Независимо от того, имеет ли это значение или нет, все сводится к коду и архитектуре, с которой вы работаете (например, давление регистра и другие факторы).