Альтернативные реализации виртуального механизма? - PullRequest
48 голосов
/ 04 декабря 2010

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

  1. Существуют ли какие-либо компиляторы, которые реализуют Виртуальный механизм любым другим способом, кроме виртуального указателя и механизма виртуальной таблицы?Насколько я видел, большинство (читай g ++, Microsoft visual studio) реализуют это через виртуальную таблицу, механизм указателей.Итак, есть ли вообще какие-либо другие реализации компилятора?
  2. Размер sizeof любого класса с виртуальной функцией будет размером указателя (vptr внутри this) на этом компиляторе , С учетом того, что сам виртуальный механизм ptr и tbl является реализацией компилятора, будет ли это утверждение, которое я сделал выше, всегда верным?

Ответы [ 11 ]

0 голосов
/ 26 апреля 2013

Ответ Тони Д. правильно указывает на то, что компиляторам разрешено использовать анализ всей программы для замены виртуального вызова функции статическим вызовом уникальной возможной реализации функции; или скомпилировать obj->method() в эквивалент

if (auto frobj = dynamic_cast<FrequentlyOccurringType>(obj)) {
    frobj->FrequentlyOccurringType::method();  // static dispatch on hot path
} else {
    obj->method();  // vtable dispatch on cold path
}

Карел Дризен и Урс Хельцле в 1996 году написали действительно увлекательный документ, в котором имитировали эффект идеальной оптимизации всей программы в типичных приложениях C ++: «Прямая стоимость вызовов виртуальных функций в C ++» . (PDF-файл доступен бесплатно, если вы Google для него.) К сожалению, они сравнивают только vtable dispatch с идеальной статической отправкой; они не сравнивали его с отправкой двоичного дерева.

Они указали , что на самом деле существует два типа виртуальных таблиц, когда вы говорите о языках (например, C ++), которые поддерживают множественное наследование. При множественном наследовании, когда вы вызываете виртуальный метод, который унаследован от второго базового класса, вам нужно «исправить» указатель объекта, чтобы он указывал на экземпляр второго базового класса. Это смещение исправления может быть сохранено как данные в vtable, или оно может быть сохранено как код в "thunk". (Подробнее см. В статье.)

Я полагаю, что все приличные компиляторы в наши дни используют thunks, но для того, чтобы проникновение на рынок достигло 100%, потребовалось 10 или 20 лет.

...