Borland Pascal. Руководство пользователя



         

Деструкторы - часть 2


Термин "полиморфический" является подходящим, так как код, обрабатывающий объект, не знает точно во время компиляции, какой тип объекта ему придется в конце концов обработать. Единственное, что он знает, это то, что этот объект принадлежит иерархии объек- тов, являющихся потомками указанного типа объекта.

Очевидно, что размеры типов объектов отличаются. Поэтому, когда наступает время очистки размещенного в динамической памяти полиморфического объекта, то как же Disрose узнает, сколько байт динамического пространства нужно освобождать? Во время компиляции из полиморфического объекта нельзя извлечь никакой информации от- носительно размера объекта.

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

Для выполнения этого освобождения памяти при позднем связы- вании деструктор нужно вызывать, как часть расширенного синтакси- са процедуры Disрose:

Disрose(P, Done);

(Вызов деструктора вне процедуры Disрose вообще не выполняет никакого освобождения памяти.) Здесь происходит на самом деле то, что сборщик мусора объекта, на который указывает P, выполняется как обычный метод. Однако, как только последнее действие выполне- но, деструктор ищет размер реализации своего типа в ТВМ и пересы- лает размер процедуре Disрose. Процедура Disрose завершает про- цесс путем удаления правильного числа байт пространства динами- ческой памяти, которое (пространство) до этого относилось к P^. Число освобождаемых байт будет правильным независимо от того, указывал ли P на экземпляр типа TSalaried, или он указывал на один из дочерних типов типа TSalaried, например, на TCommissioned.

Заметьте, что сам по себе метод деструктора может быть пуст и выполнять только эту функцию:

destructor AnObject.Done; begin end;

То, что делается полезного в этом деструкторе, не является достоянием его тела, однако при этом компилятором генерируется код эпилога в ответ на зарезервированное слово destructor. Это напоминает модуль, который ничего не экспортирует, но который осуществляет некоторые невидимые действия за счет выполнения сво- ей секции инициализации перед стартом программы. Все действия происходят "за кулисами".




Содержание  Назад  Вперед