Подтвердить что ты не робот

С++ Интервью: vtable для класса с чистой виртуальной функцией

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

Ответ 3

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