Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Прогр.на_ЯВУ_уч.пос.DOC
Скачиваний:
23
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆

Конструкторы и деструкторы

Корректная работа с виртуальными методами требует определенных правил.

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

Var

OnePoint, TwoPoint: Point;

Begin

OnePoint.Create (50,100);

…

TwoPoint.Move (21, -20); { Неправильный вызов, второй экземпляр не создан }

Каждый тип объекта, содержащий виртуальные методы, имеет таблицу виртуальных методов (ТВМ), хранящуюся в области данных. ТВМ содержит размер типа объекта и для каждого виртуального метода указатель кода, исполняющий данный метод. Конструктор устанавливает связь между вызывающим его экземпляром объекта и его ТВМ.

Так как имеется только одна ТВМ для любого типа объекта, то отдельные экземпляры объекта содержат только адрес ТВМ, а конструктор устанавливает значение этого адреса.

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

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

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

Сам по себе метод деструктора может быть пустым и выполнять только функцию связи с процедурой высвобождения памяти:

Destructor Point.Done;

Begin

End;

Деструктор дочернего типа последним действием должен вызывать соответствующий деструктор своего непосредственного предка, чтобы освободить поля всех наследуемых указателей объекта. В Турбо Паскале можно использовать служебное слово INHERITED (V7.0), с помощью которого можно вызывать методы предка без указания его имени, например:

Destructor Circle.Done;

Begin

INHERITED Done;

End;

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

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

Var

OneP: ^Point;

…

New (OneP);

OneP^.Create (50, 100);

x1 := OneP^.CetX;

…

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

New (OneP, Create(50,100));

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

Аналогично для освобождения памяти при позднем связывании используется процедура Dispose с расширенным синтаксисом:

Dispose (OneP, Done);

Самостоятельный вызов деструктора вне процедуры Dispose не приведет к освобождению памяти, занимаемой экземпляром объекта.