Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Pascal и Delphi / Borland Pascal / Объектно-ориентированное программирование /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Пример размещения объекта - Программирование от RIN.RU
Пример размещения объекта

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


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


Решение, которое не требует никаких изменений TEmployee, создает новый тип объекта, не являющийся потомком TEmployee. Тип StaffList представляет собой очень простой объект, целью которого является создание заголовков для объектов типа TEmployee. Так как TEmployee не содержит никаких указателей на следующий объект в списке, то простой тип записи TNode осуществляет этот сервис. TNode даже проще, чем StaffList в том, что TNode не является объектом, не содержит ни одного метода и не имеет никаких данных, за исключением указателя на тип TEmployee и указателя на следующий узел списка.


TStaffList содержит метод, который позволяет ему добавлять нового рабочего в связанный список записей TNode путем внесение нового экземпляра TNode непосредственно после самого себя в качестве указуемого с помощью указателя поля TNodes. Метод Add принимает указатель на объект типа TEmployee, но не сам объект. Из-за расширенной совместимости типов Турбо Паскаля указатели на любого потомка типа TEmployee также должны передаваться в TList.Add в параметре Item.


Программа WorkList описывает статическую переменную Staff типа TStaffList и строит связанный список из пяти узлов. Каждый узел указывает на отдельный рабочий объект, который является либо TEmployee, либо одним из его потомков. Перед созданием каждого динамического объекта и после того, как объект создан, возвращает число байт свободной динамической памяти. Наконец, полная структура, включающая пять записей TNode и пять объектов типа TEmployee, очищается и удаляется из динамической памяти с помощью одного вызова деструктора статического объекта Staff типа TStaffList.


Схема структур данных программы ListDemo



Удаление сложной структуры данных из динамической памяти


Деструктор Staff.Done стоит того, чтобы рассмотреть его внимательно. Уничтожение объекта TStaffList включает удаление трех различных типов структур: полиморфических объектов рабочих структур в списке, записей TNode, поддерживающих список, и (если он размещен в динамической памяти) объект TList, который озаглавливает список. Весь процесс запускается путем единственного вызова деструктора объекта TStaffList:


Staff.Done;


Код деструктора заслуживает более подробного изучения:


destructor StaffList.Done;
var
N: TNodePtr;
begin
while TNodes <> nil do
begin
N := TNodes;
Disрose(N^.Item, Done);
TNodes := N^.Next;
Disрose (N);
end;
end;


Список очищается начиная с "головы" списка с помощью алгоритма "из руки в руку", который до некоторой степени напоминает дерганье за веревку воздушного змея: два указателя (указатель TNodes внутри Staff и рабочий указатель N) изменяют свои ссылки в списке, тогда как первый элемент списка удаляется. Вызов процедуры Disрose освобождает память, занимаемую первым объектом TEmployee в списке (Item^), затем TNodes продвигается на следующую запись списка с помощью оператора TNodes := N^.Next, сама запись TNode удаляется, и процесс продолжается до полного очищения списка.


Важным моментом в деструкторе Done является способ, которым удаляются из списка объекты TEmployee:


Disрose(N.Item, Done);


Здесь N.Item является первым объектом TEmployee в списке, а вызываемый метод Done является деструктором этого объекта. Запомните, что действительный тип N^.Item^ не обязательно является типом TEmployee, однако он может быть любым дочерним типом типа TEmployee. Очищаемый объект является полиморфическим и поэтому нельзя сделать никаких предположений относительно его действительного размера или точного его типа на этапе компиляции. В приведенном выше вызове Disрose, как только Done выполнит все содержащиеся в нем операторы, "невидимый" код эпилога ищет размер реализации очищаемого объекта в ТВМ этого объекта. Метод Done передает размер процедуре Disрose, которая затем освобождает точное количество динамической памяти, в действительности занимаемой полиморфическим объектом.


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


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


var
Staff: TStaffListPtr;
begin
Disрose(Staff, Done);
.
.
.


Здесь процедура Disрose вызывает метод деструктора Done для очистки структуры в динамической памяти. Затем, когда Done завершается, Disрose освобождает память, на которую указывает Staff, удаляя, как правило, из динамической памяти также и заголовок списка.


Программа WORKLIST.PAS (находящаяся на вашем диске) использует тот же модуль WORKERS.PAS, что и раньше Она создает объект List, являющийся оглавлением связанного списка из пяти полиморфических объектов, совместимых с TEmployee, а затем удаляет всю динамическую структуру данных с помощью единственного вызова деструктора Staff.Done.



 8  Комментарии к статье  8 8  Обсудить в чате

8  В тему

Объекты

Наследование

Объекты: наследующие записи

Tехника программирования

Методы

Совмещенные код и данные

Определение методов

Объекты и модули

Программирование в "действительном залоге"

Инкапсуляция

Методы: никакого ухудшения

Расширяющиеся объекты

Cтатические методы

Полиморфизм

Совместимость типов объектов

Полиморфические объекты

Виртуальные методы

Вызов виртуальных методов

Статические или виртуальные методы?

Динамические объекты

Размещение и инициализация

Удаление динамических объектов

Деструкторы

Что же дальше?

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь