0988b24c

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


Благодаря тому, что вы повторно сможете использовать исход- ный код, применение виртуальных методов "предков" может помочь вам записывать методы порожденных классов. Например, пока вы не зададите, является элемент очередью или списком, для очереди мож- но использовать те же методы вывода, что и для списка. В классе списка вы можете записать:

virtual show:word = list_show

а в классе очереди:

virtual show:word = queue_show

Подпрограмма list_show может печатать LIST SHOW: с последую- щим выводом отдельных элементов списка. Однако в порожденном классе, если queue_show использует подпрограмму печати, она долж- на печатать собственный заголовок QUEUE SHOW: и использовать list _show только как механизм последовательного прохода по списку и печати отдельных элементов. list_show может определить передавае- мый ей тип структуры и в зависимости от этого печатать заголовок списка. Если подпрограмма для list_show посмотрит на указатель таблицы виртуальных методов передаваемой ей структуры, она сможет определить, совпадает ли указатель с указателем, установленным в подпрограмме list_init для списков (или они различны). Если ука- затель ТВМ в структуре не указывает на таблицу виртуальных мето- дов для списков, то вероятно структура является порожденным ти- пом. list_show может выполнить эту проверку с помощью следующих операторов:

cmp [([es:di]).@mptr_list],offset @TableAddr_LIST jne @@not_a_list ; пропустить печать заголовка списка

; Если мы попали сюда, то это список, и следует ; распечатать его заголовок. . @@not_a_list: ; Теперь вывести отдельные элементы списка.

Как можно вызвать класс списка и метод вывода из подпрограм- мы queue_show? Если бы вы вызвали list_show непосредственно, то в подпрограмме могла бы возникнуть проблема, если имя используемого для вывода метода изменилось. (Вы можете не помнить об изменениях в вызове queue_show.) Если в queue_show вы поместите следующий оператор:

call(es:di) method list:show

то получите бесконечный цикл, поскольку, хотя список задан как класс, для которого вызывается метод вывода, так как метод вывода является виртуальным, будет использоваться ТВМ. Поскольку ТВМ для структуры указывала бы на queue_show, вы вернулись бы к той же подпрограмме.


Наилучшим способом вызова метода класса является следующий:

call +@table_list | show

Поскольку при описании класса list_show было задано как зна- чение элемента вывода @table_list, Турбо Ассемблер автоматически транслирует данный оператор в непосредственный вызов list_show. Заметим, что хотя в списке метод вывода описывается как виртуаль- ный, задание вызова приводит к тому, что Турбо Ассемблер выполня- ет непосредственный вызов без просмотра ТВМ.

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

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

mov bx,offset @TABLEADDR_LIST call [(@table_list ptr es:bx).SHOW]

Это аналогично последовательности инструкций, которые Турбо Ассемблер использует для выполнения косвенного вызова через ТВМ.


Содержание раздела