Оптимизация одного компилятора виртуального наследования в С++?

Если у меня есть эта ситуация в проекте С++:

  • 1 базовый класс «Base», содержащий только чистые виртуальные функции
  • 1 класс «Производный», который является единственным классом, наследуемым (общедоступным) от «Базового»

Будет ли компилятор генерировать VTABLE?

Кажется, в этом нет необходимости, потому что проект содержит только 1 класс, на который может указывать указатель Base* (Derived), так что это может быть решено во время компиляции для всех случаев.

Это интересно, если вы хотите выполнить внедрение зависимостей для модульного тестирования, но не хотите нести затраты на поиск VTABLE в производственном коде.


person Sjimmie    schedule 04.02.2012    source источник
comment
Компилятор не будет знать, будет ли базовый класс унаследован в другом исходном файле или нет, поэтому он, вероятно, все равно добавит виртуальную таблицу.   -  person Some programmer dude    schedule 04.02.2012
comment
Ой, да, я мог подумать об этом, ваш ответ, вероятно, будет правильным. Таким образом, похоже, что я не буду использовать указатель на виртуальный базовый класс для регистрации зависимостей, но дам своим тестовым классам те же имена, что и производственные зависимости, и условную компиляцию моих тестовых классов (и моих производственных классов) для модульных тестов. ..   -  person Sjimmie    schedule 04.02.2012


Ответы (3)


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

  • Обычно компилятор видит только одну единицу компиляции. Он не может знать, что существует только один подкласс, потому что через пять месяцев вы можете написать другой подкласс, скомпилировать его, получить из резервной копии несколько древних объектных файлов и связать их все вместе.
  • В то время как оптимизации времени компоновки действительно видят всю картину, они обычно работают с представлением программы гораздо более низкого уровня. Такое представление позволяет, например. встраивание статических вызовов, но не представляет информацию о наследовании (кроме, возможно, как необязательных метаданных) и уже имеет явное изложение виртуальных вызовов и виртуальных таблиц. Я знаю, что это относится к оптимизации всей программы Clang и IIRC gcc, которая также работает с некоторыми низкоуровневыми IR (GIMPLE?).
  • Также обратите внимание, что при динамической загрузке вы можете по-прежнему добавлять дополнительные подклассы спустя долгое время после компиляции и LTO. Вам это может не понадобиться, но если бы я был писателем компилятора, я бы устал добавлять оптимизацию, которая позволяет людям по-царски ломать виртуальные вызовы в очень специфических, трудно отслеживаемых обстоятельствах.
  • Это редко стоит проблем - если вам не нужны виртуальные вызовы (например, потому что вы знаете, что вам больше не понадобятся подклассы), не делайте ничего virtual. Просмотрите свой дизайн. Если вам нужен некоторый полиморфизм, но не вся мощь виртуального пространства, используйте странно повторяющийся шаблон шаблона. может помочь.
person Community    schedule 04.02.2012
comment
Спасибо, вы подтолкнули меня к поиску полиморфного решения во время компиляции, и у кого-то уже есть что-то, что, я думаю, я могу использовать: skepticalmethodologist.wordpress.com/2008/07/20/ - person Sjimmie; 04.02.2012

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

person CB Bailey    schedule 04.02.2012
comment
Я использую gcc, здесь есть список параметров оптимизации: gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Optimize-Options.html. Но я не могу найти тот, который кажется применимым. Дело в том, что «может быть» на самом деле неприемлемо. - person Sjimmie; 04.02.2012
comment
@Sjimmie: я предполагаю, что это не оптимизирует его. Вы проверили скомпилированный код? - person Karoly Horvath; 04.02.2012

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

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

Очевидно, что автор компилятора не счел нужным заморачиваться этим. Наверное, потому что он не будет использоваться очень часто.

person Bo Persson    schedule 04.02.2012