C ++ Интервью: vtable для класса с чисто виртуальной функцией - PullRequest
13 голосов
/ 03 октября 2011

Мне задали этот вопрос сегодня !!(это было очень неудобное телефонное интервью ..):

В чем разница между vtable для класса с виртуальными функциями и класса с чисто виртуальными функциями?

Теперь я знаю, что в стандарте C ++ ничего не говорится о vtables или даже о существовании v-таблицы. Однако, теоретически, каким будет ответ?

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

Будет ли гипотетический компилятор создавать виртуальную таблицу для класса только с чисто виртуальными функциями?Что если класс содержит чисто виртуальные функции с определениями?(как показано в: http://www.gotw.ca/gotw/031.htm).

Ответы [ 3 ]

23 голосов
/ 03 октября 2011

В случае не чистых виртуальных функций каждая запись в vtable будет ссылаться на final-overrider или thunk , который адаптирует указатель this при необходимости.В случае чисто-виртуальной функции запись в виртуальной таблице обычно содержит указатель на универсальную функцию, которая выдает жалобу и прерывает программу с каким-то разумным сообщением (чисто виртуальная функция вызывается в этом контексте). или подобное сообщение об ошибке).

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

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

Что если класс содержит чисто виртуальные функции с определениями?

Это будетне влияет на vtable.Vtable используется только для динамической диспетчеризации, и вызов никогда не будет динамически отправляться на определение чисто виртуальной функции (т. Е. Вы можете вручную передать только виртуальную функцию, отключив динамическую диспетчеризацию с указанием имени типа: x.base::f() вызовет base::f, даже если он чисто виртуальный , но x.f() никогда не будет отправлен на base::f, если он чисто виртуальный.

1 голос
/ 03 октября 2011

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

0 голосов
/ 03 октября 2011

Я могу вам сказать, что «чистые» абстрактные классы (классы только с чисто виртуальными функциями) используются Microsoft (и MS VC ++) для своих интерфейсов COM.Возможно, он говорил об этом.«Внутреннее» представление COM - это указатель на vtable.Чистые абстрактные классы в MS VC ++ реализованы таким же образом, поэтому вы можете использовать их для представления COM-объектов.Ясно, что если в вашем классе есть другие виртуальные функции, вы не можете просто перезаписать его vtable на COM vtable: -)

...