Удаление динамических объектов. Деструкторы


Динамическими могут быть объекты со статическими и виртуальными ме­тодами. Удаление динамических объектов может быть с помощью процедур Dispose или с помощью деструктора.

Подобно другим динамическим типам данных динамические объекты со статическими методами могут удаляться с помощью Dispose. Например:

Dispose ( P1 );.

Пример программы с динамическим объектом со статическими методами дан в листинге 5.

Листинг 5.Динамические объекты со статическими методами.

Program novirt; Uses Crt; { Объявления: }
Type ObjName1 = object { - объекта-предка }

Fl1 : integer;

Procedure Met1;

Procedure Met2; End;

ObjName2 = object ( ObjName1 ) { - объекта-потомка }

Procedure Met2; End;

PobjName1 = ^ObjName1; {-тип - указатель на объект ObjName1 }

PObjName2 = ^ObjName2; { - " " " " ObjName2 }

{ -- Методы объекта ObjName1 ------- }

Procedure ObjName1.Met1; Begin

Met2; { - вызов только метода ObjName1.Met2 !!}

End;

Procedure ObjName1.Met2; Begin FL1 := 12;

Writeln ( 'Работает метод ObjName1.Met2: Fl1 = ', FL1) End;

{ -- Методы объекта ObjName2 ------ }

Procedure ObjName2.Met2; Begin FL1 := 34;

Writeln ( 'Работает метод ObjName2.Met2: Fl1 = ', FL1) End;

Var V1 : PobjName1; { - динамический объект V1 } V2 : PObjName2; { - " " V2 }

{ ------ Основная программа----------- }

Begin ClrScr;

Assign (Output, 'dnovirt.res'); Rewrite (output);

Writeln ('ДИНАМИЧЕСКИЕ ОБЪЕКТЫ, СТАТИЧЕСКИЕ МЕТОДЫ'); Writeln ('Работаем с VI - экземпляром типа предка');

New ( V1 ); { - создание динамического объекта V1 }

V1^.Met1; { - вызов метода ObjName1 .Met1; }

Vl1.Met2; { - " " ObjName1.Met2; }

Dispose ( V1 ); { - удаление объекта V1 }

Writeln ('Работаем с V2 - экземпляром типа потомка');

New ( V2 ); { - создание динамического объекта V2 }

V2^.Met1; { - вызывает ВСЕГДА метод ObjName1.Met2,

а не ObjName2.Met2 }

V2^.Met2; { - вызов метода ObjName2.Met2; }

Dispose ( V2 ); { - удаление объекта V2 }

Close (Output);

End.

Для освобождения ОП динамических объектов с виртуальными методами используются особые методы - деструкторы. В качестве их имен рекомендует­ся употреблять имя Done. Они предназначены для выполнения завершающих действий программы. Деструктор размещается вместе с другими методами объекта в определении типа и оформляется так же, как обычный метод-процедура, но слово PROCEDURE заменяется словом DESTRUCTOR. Например: Destructor TObjl.Done;.

Вызов деструктора (Done) вне процедуры Dispose не приведет к автома­тическому освобождению ОП, занимаемой экземпляром объекта, т. е. недо­пустимо Р1^.Done;.

Для корректного освобождения ОП, которую реально занимает экземпляр динамического объекта с поздним связыванием, деструктор надо вызывать с помощью расширенного типа процедуры Dispose. Он имеет 2 параметра: имя указателя на объект и имя деструктора. Например:

Dispose ( PI,Done);

где Done - имя деструктора объекта, на который указывает Р1.

Деструктор выполняется как обычный метод. Когда будет выполнено по­следнее его действие, если объект содержит виртуальные методы, то деструк­тор производит поиск размера объекта в ТВМ и передает его процедуре Dispose, которая и освобождает правильное количество байт, независимо от того, указывал ли Р1 на тип предка или потомка.

Метод деструктора может быть и пустым, так как основная информация содержится не в теле деструктора, а связана с его заголовком, содержащим слово Destructor.

Деструктор потомка последним своим действием должен вызывать соот­ветствующий деструктор своего непосредственного предка, чтобы освободить ОП всех наследуемых указателей объекта. Например:

Destructor Tobj1.Done;

Begin

. . . INHERITED Done;

End;

Для корректного освобождения ОП при использовании полиморфных объ­ектов также надо использовать процедуру Dispose расширенного вида. По­лиморфным является объект, значением которого могут быть экземпляры различных (таких же или порожденных) типов. Эти правила относятся и к указателям на объекты: адресуемый ими объект также будет полиморфным.

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

Деструктор может объединять удаление объекта с другими действиями, необходимыми для корректного удаления. Например, при удалении динамиче­ского объекта может понадобиться не только освобождение занимаемой им ОП. Объект может содержать указатели на динамические объекты или свя­занные структуры (стеки, очереди, списки), которые надо удалить в опреде­ленном порядке. Все операции для удаления динамического объекта должны объединяться в один метод, чтобы объект мог быть уничтожен с помощью одного вызова. Например: Objl .Done; или Dispose ( Pi, Done );.

Для одного и того же типа объекта может быть несколько деструкторов. Деструкторы можно наследовать. Они могут быть статическими или вирту­альными. Например: Destructor Done; Virtual;

Для динамических объектов целесообразно объявлять виртуальный дест­руктор, даже если объект не содержит других виртуальных методов. Если де­структор виртуальный, связь с конкретным экземпляром объекта осуществля­ется в процессе выполнения программы. Следовательно, в зависимости от ти­па экземпляра объекта деструктор будет обращаться к ТВМ-предка или к ТВМ-потомка иерархии объектов. Размеры выделяемой для них ОП могут быть разными. При этом для каждого типа объекта выполняется деструктор, соот­ветствующий данному типу объекта.

Деструкторы работают с динамическими объектами. Но применение дест­руктора к статическим объектам не является ошибкой и не приведет к некор­ректной работе программы.

Пример программы с динамическим объектом с виртуальными методами и с использованием деструктора приведен в листинге 6.

Листинг 6.Динамические объекты с виртуальным методом.

Program Dvirt; {$F+,R+} Uses Crt;

Type ObjName1 = object { - тип объекта-предка }

Fl1 : integer;

Constructor Met1; {- конструктор типа ObjName1 }

Destructor Done; Virtual; {- деструктор типа ObjName1 } Procedure Met2; Virtual; End;

ObjName2=object (ObjName1) {-тип потомка ObjName1 ) Procedure Met2; Virtual;

Destructor Done; Virtual; {-деструктор типа ObjName2 } End;

PobjName1 = ^ObjName1; {- тип - указатель на объект ObjName1}
PObjName2 = ^ObjName2; { -" " " ObjName2 }

{ Методы объекта ObjName1 }

Constructor ObjName1.Met1; Begin

Met2; {- вызов Met2 из конструктора }

End;

Destructor ObjName1.Done; Begin

Writeln ('Освобождается ОП объекта типа ObjName1'); End;

Procedure ObjNamel.Met2;

Begin Fl1 := 12;

Writeln ('Работает метод ObjName1.Met2: Fl1= ', Fl1) End;

{ Методы объекта ObjName2 -- }

Procedure ObjName2.Met2;

Begin Fl1 := 34;

Writeln ('Работает метод ObjName2.Met2: Fl1 = ', Fl1) End;

Destructor ObjName2.Done; Begin

Writeln ('Освобождается ОП объекта типа ObjName2'); End;

Var V1 : PobjName1; { - динамический объект V1 }

V2 : PObjName2; { - " " V2 }

{ -------- Основная программа --------- }

Begin ClrScr;

Assign (Output, 'Dvirt.res'); Rewrite (output);

Writeln ('ДИНАМИЧЕСКИЕ ОБЪЕКТЫ, ВИРТУАЛЬНЫЕ МЕТОДЫ' ); Writeln ('Работаем с V1 - экземпляром типа предка');

{Вызывается конструктор Met1 для экземпляра V1 - предка:}

New (V1,Met1); {- создание динамического объекта V1 }
V1^.Met2; { - вызов метода ObjName1.Met2; }

{ Удаление объекта - только с помощью Dispose и Done: } Dispose (V1,Done); {- удаление объекта V1 деструктором

ObjName1.Done }

Writeln ('Работаем с V2- экземпляром типа потомка');

{Вызывается конструктор Met1 для экземпляра V2 - потомка V1:}
New ( V2, Met1 ); { - создание динамического объекта V2 }
V2^.Met2; { - вызов метода ObjName2 .Met2; }

{ Удаление объекта - только с помощью Dispose и Done: } Dispose (V2,Done); { - удаление объекта V2 деструктором

ObjName2.Done}

Close (Output);

End.

Общие правила использования конструкторов и деструкторов: Constructor - для виртуальных методов, для создания ТВМ при исполь­зовании статических и динамических объектов.

Destructor - для освобождения ОП динамических объектов, содержащих виртуальные методы.

Контрольные вопросы

1. Что такое объектно-ориентированное программирование? Каковы его особенности и область применения?

2. Назовите свойства объектов.

3. Что такое инкапсуляция? Как объявить объект?

4. Что такое наследование и переопределение, предок, потомок? Как объявить объ­ект-потомок?

5. Что такое полиморфизм? Как переопределить статический, виртуальный методы?

6. Как создать, удалить динамический объект?

7. Что такое конструктор, деструктор? Когда надо их использовать?



Дата добавления: 2019-12-09; просмотров: 627;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.014 сек.