Объяснение виртуальной таблицы

Возможный дубликат:
Понимание записей vtable

Использование g++ версии 4.6.3, 64-битная машина. Я знаю, что компилятор может свободно реализовывать виртуальные функции так, как он хочет. Я хочу знать, что здесь произошло.

Мои занятия:

#include <iostream>
class test
{
    public:
    virtual void func(){std::cout<<"in class test";}
};

int main()
{
    test obj;
    obj.func();
    return 0;
}

Глядя на виртуальную таблицу, сгенерированную компилятором,

Vtable for test
test::_ZTV4test: 3u entries
0     (int (*)(...))0 (<---- what is this? )
8     (int (*)(...))(& _ZTI4test)
16    (int (*)(...))test::func

По смещению 8 это RTTI

По смещению 16 это запись для виртуальной функции.

Мой вопрос: почему есть запись для NULL по смещению 0 или, другими словами, какова цель первой записи?

P.S. Я думал, что это может быть связано с выравниванием, но затем я добавил больше виртуальных функций, но запись RTTI все еще была со смещением 8.


person Anon    schedule 27.10.2012    source источник
comment
Я предполагаю, что он зарезервирован для деструктора (который вы не добавили).   -  person john    schedule 27.10.2012
comment
@John, добавлен деструктор, все тот же вывод. Кроме того, необходим ли деструктор, который всегда будет частью v-таблицы?   -  person Anon    schedule 27.10.2012
comment
Очень часто используется виртуальный деструктор, если у вас есть какие-либо виртуальные функции. Но это не обязательно. О, хорошо, моя догадка была ошибочной.   -  person john    schedule 27.10.2012
comment
@Anon - Вы обязательно пометили деструктор как виртуальный? Объяснение Джона кажется довольно разумным, поэтому я просто хотел перепроверить.   -  person Xavier Holt    schedule 27.10.2012
comment
@XavierHolt, сначала я этого не делал, а просто попытался, как предложили вы и Джон. RTTI по-прежнему находится на смещении 8.   -  person Anon    schedule 27.10.2012
comment
@Анон - Хм. Не знаю, тогда - удачи!   -  person Xavier Holt    schedule 27.10.2012


Ответы (1)


Я считаю, что первая запись или запись в 0 является смещением к верхнему указателю.

См. следующий соответствующий вопрос о переполнении стека

Просматривая оставшуюся часть -fdump-class-hierarchy из исходного кода, большинство классов, кажется, имеют первую запись как (int (*)(...))0 , единственные классы, которые не имеют ее как первую запись, имеют ее как вторую и имеют первую запись как смещение к родительскому классу с учетом иерархии классов C++ STL для потоков.

В соответствующем вопросе дана мертвая ссылка на некоторые примеры vtable, я полагаю, что доступна живая версия этой ссылки здесь

Другой полезный ресурс, подробно описывающий структуру виртуальных таблиц, находится здесь.

person Appleman1234    schedule 27.10.2012
comment
Ага. Это смещение к верхнему указателю. Среди прочего, это используется для реализации dynamic_cast<void*>. Это приведение дает указатель на наиболее производный объект. Стандарт, конечно же, ничего не говорит о виртуальных таблицах или о том, как реализация будет выполнять требуемую функцию dynamic_cast<void*>. - person David Hammen; 27.10.2012