- •Внутреннее
- •Внутренний формат данных объекта имеет
- •Если объектн
- •Внутренний формат данных объекта.
- •TPerson
- •Таблица виртуальных методов.
- •Первое слово таблицы виртуальных методов содержит размер эк
- •Второе слово таблицы виртуальных методов содержит отрицател
- •Разрешение проверок границ диапазонов и проверок вызовов виртуальных методов замедляет выполнение программы и
- •Третье слово ТВМ содержит смещение сегмента данных объектно
- •Четвертое слово ТВМ резервируется и всегда равно 0.
- •Начиная со смещения 8,
- •Конструкторы объектных типов содержат специальный код, который запоминает смещение таблицы виртуальных
- •Для непосредственной работы с ТВМ используются две функции
- •Примененная к экземп
- •Функция TypeOf может использоваться для проверки фактического типа экземпляра.
- •Таблица динамических методов.
- •Таблица динамических методов.
- •Переопределим типы TStaf и
- •Первое слово
- •Таблица динамических методов.
- •Вызов статических методов.
- •Например:
- •Вызов статических методов.
- •Для вызова виртуального метода компилятор генерирует код, который:
- •Правила совместимости для объектных типов позволяют Staf указывать на TStaf и на ТТеасher
- •Вызов динамических методов.
- •Если бы метод GetSum типа TStaf описывался как
- •Вызов динамических методов.
- •Вызов динамических методов.
- •Вызов динамических методов.
- •Вызов конструкторов и деструкторов.
- •Вызов конструкторов и деструкторов.
- •Вызов конструкторов и деструкторов.
- •Вызов конструкторов и деструкторов.
Первое слово
Таблица динамических методов. |
23 |
Таблица динамических методов. |
24 |
Вызов статических методов. |
25 |
Например: |
|
|
|
|
|
|
|
1. в |
типе |
Tperson |
определим процедуру |
||
|
ShowName |
|
|
|
|
|
|
2. введем переменную Person типа ^TPerson, |
|
||||
|
Теперь |
вызов |
Person^.ShowName |
будет |
||
|
кодироваться следующим образом: |
|
||||
|
les DI, |
Person; |
|
{загрузить Person в ES:DI} |
|
|
|
push ES; {передать как параметр Self} |
|
||||
|
push DI; |
|
|
|
|
|
|
call TPerson.ShowName; |
{непосредственный вызов |
||||
|
|
|
|
ShowName} |
|
|
|
|
|
|
|
|
|
Вызов статических методов. |
26 |
Вызов статических методов. |
27 |
Для вызова виртуального метода компилятор генерирует код, который:
1.выбирает адрес таблицы виртуальных методов из поля таблицы виртуальных методов объекта,
2.вызывает метод, используя связанную с ним точку входа.
Например, для переменной Staff типа PStaff вызов Staff.GetSum будет генерировать следующий код:
les DI, Staff; {загрузить Staff в ES:DI} |
push ES; {передать как параметр Self} |
push DI; |
mov DI,ES:[DI+6]; {извлечь смещение ТВМ из поля ТВМ} |
call DWORD PTR [DI+12]; {вызвать запись ТВМ для GetSum} |
Вызов виртуальных методов. |
28 |
Правила совместимости для объектных типов позволяют Staf указывать на TStaf и на ТТеасher или на любых других потомков TStaf.
Если просмотреть приведенные ранее таблицы виртуальных методов |
TStaff и ТТеасher, можно увидеть, что для типа TStaff точка входа со |
смещением 12 в таблице виртуальных методов указывает на |
TStaff.GetSum. |
Таким образом, в зависимости от фактического типа Staf |
во время вызова инструкция CALL вызывает либо |
TStaf.GetSum, либо ТТеасher.GetSum, либо метод |
любого другого потомка TStaf. |
Вызов виртуальных методов. |
29 |
Вызов динамических методов. |
30 |
Если бы метод GetSum типа TStaf описывался как |
|
|
динамический метод с индексом 10, то вызов Staf^.Getsum, где |
|
|
Staf имеет тип PStaf, привел бы к генерации следующего кода: |
|
|
les DI,Staff; {загрузить Staff в ED:DI} |
|
|
push ES; |
{передать как параметр Self} |
|
push DI; |
|
|
mov DI,ES:[di+6]; |
|
|
{извлечь смещение ТДМ из поля ТВМ} |
|
|
mov AX,10; |
|
|
{загрузить в АХ индекс динамического метода} |
|
|
call Dispatch; |
|
|
{вызов подпрограммы обработки вызовов} |
|
|
|
Вызов динамических методов. |
31 |
Вызов динамических методов. |
32 |