Ответы на экзаменационные вопросы № 1-34 по дисциплине "Программирование" (Средства модульного программирования в системе Турбо-Паскаль. ООП. Объекты в динамической памяти), страница 30

Var Staff: Tstaff;

..........................................

begin

new(Staff);

Staff^.Init('Иванов', 1000,100);

.............................................

Дальнейшие вызовы методов осуществляются, как и вызов метода Init, с использованием имени указателя и ссылочного символа после него.

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

New( Staff, Init ('Иванов',1000,100));

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

Staff.•= new (Tstaff, Init ('Иванов', 1000,100));

Освобождение динамической памяти, выделенной экземпляру объекта, производится с помощью процедуры dispose. С освобождением динамической памяти связан особый вид методов, называемых деструкторами (destructor). В общем случае деструктор предназначен для выполнения каких-либо завершающих действий в программе. Как правило, деструктор имеет имя Done. При этом слово procedure заменяется на слово destructor. Деструкторы могут наследоваться и быть виртуальными, в отличие от конструкторов. В одном объекте может быть определено несколько деструкторов. Хотя понятие деструктор и противоположно конструктору, деструкторы реально необходимы только в случае работы с динамической памятью.

Освобождение динамической памяти должно производиться с помощью расширенного вызова процедуры dispose:

Dispose (staff, done);

Особенно полезно и удобно использовать деструкторы для удаления из памяти полиморфных объектов. Полиморфными называются дочерние объекты, которым присваивается экземпляры родительского типа. Например, пусть есть Type Tstaffptr=ATstaff;

Tteacherptr=ATteacher;

В этом случае возможно присваивание: Staffptr=:Teacherptr;

После выполнения присваивания Staffptr содержит ссылку на область большего размера, чем память, отводимая Tstaffptr. Для того чтобы освободить правильное число байтов, необходим расширенный вызов процедуры dispose с деструктором в качестве второго параметра. В этом случае деструктор получает копию параметра self через стек. С помощью этого параметра методу (деструктору в частности) становится доступной таблица виртуальных методов, где содержится размер экземпляра данного объекта в байтах. Этот размер передается процедуре dispose.

Деструктор может быть пустым (не содержать операторов между begin и end). В этом случае его единственная функция - это связь с процедурой dispose.

Если в программе используется сложная динамическая структура данных, содержащая, например, указатели на динамические структуры, когда освобождение памяти должно происходить з определенном порядке, все действия по освобождению памяти лучше объединять в один метод, инкапсулирующий все детали очистки. В общем случае деструкторы лучше делать виртуальными.

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

Type link=^llink;

Llink=object

C:char; Next:link;

Constructor Init (chxhar);

Procedure Add(l:link);

Destructor Done (var Mink);

End;

Constructor llink.lnit;

Begin

C:=ch; next:=nil

End:

Procedure Ilink.Add;

Begin

Next:=l

End;

Destructor Ilink.Done;

Begin

Write(c); l:=next

End;

Varq,top:link;ch:char;

Begin

Writein('BBOfl'); Top:= nil;

Readin(ch); Repeat

New(q,lnit(ch)); q^.add(top); Top:=q;

Readln(ch) Until ch=7;

Repeat

Dispose (q,Done(q));             Until q= nil;

Readln End.

35.ООП. Вложение объектов: композиция и агрегация объектов. Объекты-контейнеры.


{процедура пустая, т.к. у объектов} {не будет экземпляров}