TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

Пример размещения динамического объекта 

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

             Построение связанного списка объектов требует,  чтобы каждый
        объект   содержал  указатель  на  следующий  объект  списка.  Тип
        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.


                    │

          List      │      Node           Node             Node
        ┌───────┐      ┌────┬────┐     ┌────┬────┐      ┌────┬────┐
        │       │   │  │    │    │     │    │    │      │    │    │
        │    O──┼────> │  O │  O─┼───> │  O │  O─┼────> │  O │  O─┼───┐
        │       │   │  │  │ │    │     │  │ │    │      │  │ │    │   │
        └───────┘      └──┼─┴────┘     └──┼─┴────┘      └──┼─┴────┘   │
                    │     │               │                │        ──┴──
                          v               v                v         ───
                    │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ─
                      │    Name     │ │    Name     │ │    Name     │
                    │ ├─────────────┤ ├─────────────┤ ├─────────────┤
                      │    Title    │ │    Title    │ │    Title    │
                    │ ├─────────────┤ ├─────────────┤ ├─────────────┤
                      │    Rate     │ │    Rate     │ │    Rate     │
                    │ ├─────────────┤ ├─────────────┤ ├─────────────┤
                      │             │ │             │ │             │
          Сегмент   │   Динамически распределяемая область
          данных        памяти (динамический)
        (статические│
         объекты)
                    │

             Рис. 9.2 Схема структур данных программы 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.
/

Содержание

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz