Иллюстрированный самоучитель по Delphi 7 для профессионалов

Методы

Принципиально отличаются от статических виртуальные и динамические методы. Они должны быть объявлены путем добавления соответствующей директивы virtual или dynamic. Обе эти категории существовали и в прежних версиях языка Pascal. С точки зрения наследования методы этих двух видов одинаковы: они могут быть перекрыты в дочернем классе только одноименными методами, имеющими тот же тип.

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

Естественно, что этот механизм должен быть каким-то образом связан с передаваемым объектом. Для этого используются таблица виртуальных методов (Virtual Method Table, VMT) и таблица динамических методов (Dynamic Method Table, DMT).

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

Такая таблица есть для каждого класса (объектного типа). В ней хранятся адреса всех виртуальных методов класса, независимо от того, унаследованы ли они от предка или перекрыты в данном классе. Отсюда и достоинства, и недостатки виртуальных методов: они вызываются сравнительно быстро, однако для хранения указателей на них в таблице VMT требуется большое количество памяти.

Динамические методы вызываются медленнее, но позволяют более экономно расходовать память. Каждому динамическому методу системой присваивается уникальный индекс. В таблице динамических методов класса хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе. При вызове динамического метода происходит поиск в этой таблице; в случае неудачи просматриваются таблицы DMT всех классов-предков в порядке иерархии и, наконец, класс TObject, где имеется стандартный обработчик вызова динамических методов. Экономия памяти налицо.

Для перекрытия и виртуальных, и динамических методов служит директива override, с помощью которой (и только с ней!) можно переопределять оба этих типа методов. Приведем пример:

type
TFirstClass = class
FMyFieldl: Integer;
FMyField2: Longint;
procedure StatMethod;
procedure VirtMethodl; virtual;
procedure VirtMethod2; virtual;
procedure DynaMethodl; dynamic;
procedure DynaMethod2; dynamic;
end;
TSecondClass = class(TMyObject)
procedure StatMethod;
procedure VirtMethodl; override;
procedure DynaMethodl; override;
end;
var
Objl: TFirstClass;
Obj2: TSecondClass;

Первый из методов в примере создается заново, остальные два – перекрываются. Попытка применить директиву override к статическому методу вызовет ошибку компиляции.

Примечание
Будьте внимательны: попытка перекрытия с директивой не override, a virtual или dynamic приведет на самом деле к созданию нового одноименного метода
.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.