ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Category:

C++: указатель на таблицу виртуальных методов

Продолжаем тему из предыдущего поста «C++: запись объекта в файл и виртуальные функции».

Немного углубимся в то, как компилятор среды «Visual Studio Community 2017» в Windows работает с указателем на таблицу виртуальных методов на примере программы empl_io.cpp из учебника Лафоре (стр.574). Схема классов:


Запишем в файл в режиме ios::binary один объект класса «управленец», два объекта класса «ученый» и один объект класса «рабочий». Результат — файл размером 384 байта:


Я обвел красным группы байтов, относящиеся к разным объектам. В каждой группе первые 4 байта не входят в состав объекта, это сохранена переменная типа int с информацией о типе (классе) объекта. Об этом уже упоминалось в предыдущем посте.

К каждому объекту компилятор добавил дополнительное поле-указатель __vfptr на таблицу виртуальных методов (на рисунке его байты подчеркнуты жирной красной линией). Размер поля в нашем случае (32-разрядное приложение) — 4 байта.

В каждом объекте поля, доставшиеся данному производному классу от базового класса, занимают 68 байтов (поле name имеет размер 64 байта (массив-буфер из 32 символов wchar_t), поле number — 4 байта (тип unsigned long)). Расчет размера файла:

тип объекта(4) + управленец(__vfptr(4) + 68 + поле «title» 64 + поле «dues» (double) 8) +
+ тип объекта(4) + ученый(__vfptr(4) + 68 + поле «pubs» (int) 4) +
+ тип объекта(4) + ученый(__vfptr(4) + 68 + поле «pubs» (int) 4) +
+ тип объекта(4) + рабочий(__vfptr(4) + 68) =

= тип объекта(4) + 144 + тип объекта(4) + 76 + тип объекта(4) + 76 + тип объекта(4) + 72 =

= 148 + 80 + 80 + 76 = 384 байта

Выводы. 1. Указатель на таблицу виртуальных методов для объектов разных классов, производных от одного базового класса, различается (это понятно, ведь реализация виртуальных методов в каждом производном классе своя):

FC 5A EE 00 (на самом деле, значение этого указателя равно 00 EE 5A FC, помним про little endian)
1C 5B EE 00
98 5A EE 00

2. Указатели на таблицу виртуальных методов для разных объектов одного класса равны. То есть для объектов одного класса используется одна таблица виртуальных методов. Это видно на рисунке: второй и третий объекты, записанные в файл, одного класса и указатель на таблицу виртуальных методов у них совпадает:

1C 5B EE 00

3. Указатель на таблицу виртуальных методов остается неизменным лишь в пределах одного сеанса работы с программой. (Чтобы это проверить, после записи файла, изображенного выше на рисунке, я закрыл программу, а затем снова вошел в нее и записал в этот же файл те же тестовые данные. Указатели на таблицу виртуальных методов изменились.)

Важное замечание. Пишут, что разные компиляторы по-разному организуют работу с виртуальными методами. (Например, поле-указатель на таблицу виртуальных методов другие компиляторы не обязательно поставят первым в объекте.) Поэтому нужно понимать, что выводы, сделанные в этом посте, относятся только к указанному компилятору и указанной операционной системе, а в других случаях могут не соответствовать действительности.
Tags: Образование, Программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments