Объект содержит записи для всех его полей, а также дополнительное пространство для хранения указателя на таблицу виртуальных методов. VMT содержит больше, чем просто указатели виртуальных методов. Я объясню больше о VMT на моем веб-сайте, включая диаграмму.
По-видимому, в Delphi 2009 добавлено еще одно скрытое поле в дополнение к указателю VMT для хранения монитора синхронизации. Вы можете определить, будет ли он добавлен в начале или в конце класса, с помощью простого кода:
type
TTest = class
FField: Integer;
end;
var
obj: TTest;
ObjAddr, FieldAddr: Cardinal;
begin
Assert(TTest.InstanceSize = 12);
obj := TTest.Create;
ObjAddr := Cardinal(obj);
FieldAddr := Cardinal(@(obj.FField));
writeln(FieldAddr - ObjAddr);
end.
Если он печатает значение 4, то поле монитора должно быть в конце объекта, потому что 4 учитывает только размер указателя VMT. Если он печатает значение 8, то поле монитора должно быть в начале, рядом с указателем VMT.
Полагаю, вы найдете монитор в самом начале. В противном случае это означает, что компоновка объекта-потомка - это не просто компоновка базового объекта со всеми добавленными новыми полями. Это будет означать, что смещение поля монитора зависит от типа объекта во время выполнения, что усложняет реализацию.
Когда класс реализует интерфейс, структура объекта включает в себя больше скрытых полей. Поля содержат указатели на значение ссылки на интерфейс объекта. Когда у вас есть ссылка IUnknown
на объект, указатель, который он содержит, не совпадает с указателем на поле VMT объекта, которое вы имеете при использовании обычной ссылки на объект. Значение указателя IUnknown
будет адресом скрытого поля. Я написал подробнее о компоновке классов, которые реализуют интерфейсы .