Для лучшего понимания особенностей использования тэговых типов и свойств диспетчеризации вызовов операций, может оказаться полезным рассмотрение возможной модели реализации механизма диспетчеризации.
Следует подчеркнуть, что не смотря на достаточную реалистичность нашей модели, мы рассматриваем только возможную модель, сознательно опуская множество нюансов, а это значит, что реализация для какого-либо конкретного компилятора может не соответствовать этой модели.
Согласно нашей модели, подразумевается, что тэг - это указатель на таблицу диспетчеризации вызовов.
Каждый элемент такой таблицы содержит указатель на реализацию подпрограммы которая является примитивной операцией.
Диспетчеризация осуществляется путем выполнения косвенного вызова с помощью таблицы диспетчеризации, а необходимая примитивная операция выбирается как соответствующий индекс элемента в таблице диспетчеризации.
Таким образом, наша модель для рассмотренной ранее иерархии типов (Root, Child_1, Child_2 и Grand_Child_2_1) будет иметь следующий вид:
| ------------ Root'Tag ---> | The_Name |---> The_Name для Root ------------
------------ Child_1'Tag ---> | The_Name |---> The_Name для Child_1 ------------ ------------ Child_2'Tag ---> | The_Name |---> The_Name для Child_2 ------------ ------------ Grand_Child_2_1'Tag ---> | The_Name |---> The_Name для Grand_Child_2_1 ------------ |
Следует заметить, что наша иллюстрация максимально упрощена и не содержит множества предопределенных примитивных операций, кроме того, описания типов иерархии также были очень простыми.
Базовый адрес каждой таблицы соответствует значению тэга и содержится в значении надклассового объекта.
Примечательно также, что в таблицах диспетчеризации не содержатся указатели на надклассовые операции (подобные процедуре Show), поскольку они не являются диспетчеризуемыми операциями.
Таким образом, при динамическом связывании во время выполнения программы, на основе информации о тэге объекта осуществляется выбор соответствующей таблицы диспетчеризации.
|
with Simple_Objects; use Simple_Objects; package Simple_Objects_New is type Grand_Child_1_1 is new Child_1 with null record; procedure New_Method (Self: in Grand_Child_1_1); procedure New_Method_Call (Self: in Grand_Child_1_1'Class); . . . end Simple_Objects_New; |
|
-------------- Grand_Child_1_1'Tag ---> | The_Name |---> The_Name для Child_1 -------------- | New_Method |---> New_Method для Grand_Child_1_1 -------------- |