Ада-95. Компилятор GNAT

       

Обобщенные ссылочные типы


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

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

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

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

Например:

Int_Var : aliased Integer; Int_Const : aliased constant Integer := 0;

Чтобы получить ссылочные значения для статических объектов которые допускают использование косвенного доступа необходимо использовать атрибут 'Access.

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

или зарезервированного слова constant.

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

Например:

type Int_Var_Ptr is access all Integer; type Int_Const_Ptr is access constant Integer;

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




Следовательно, такое описание используется для получения ссылок на статические переменные.

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

Следовательно, такое описание чаще всего используется для получения ссылок на константы и в более редких случаях для получения ссылок на переменные.

Рассмотрим следующий пример:

procedure General_Access_Demo is

type Int_Var_Ptr_Type is access all Integer; A : aliased Integer; X, Y : Int_Var_Ptr_Type;

begin

X := A'Access; Y := new Integer; end General_Access_Demo;

Здесь, переменная A имеет тип Integer и является косвенно доступной.

Переменные X и Y имеют тип Int_Var_Ptr_Type который является обобщенным ссылочным типом.

В результате, внутри процедуры, переменная X ссылается на статическую переменную A, ссылка на которую получена с помощью атрибута 'Access.

Переменная Y ссылается на объект типа Integer который размещен в области динамической памяти.

Ада позволяет использовать обобщенные ссылочные типы для формирования ссылок на отдельные элементы внутри составных типов данных (таких как массив и/или запись), например:

type Array_Type is array (Positive range < >) of aliased Integer;

type Record_Type is

record

A_Int_Var : aliased Integer; Int_Var : Integer; end record;

type Int_Var_Ptr_Type is access all Integer;

В данном случае тип Array_Type - это массив, состоящий из косвенно доступных элементов типа Integer, а тип Record_Type - это запись, у которой поля A_Int_Var и Int_Var имеют тип Integer, причем поле A_Int_Var косвенно доступно, а поле Int_Var - нет.

Таким образом, значения типа Int_Var_Ptr_Type могут ссылаться на индивидуальные элементы массивов, принадлежащих к типу Array_Type, и поле A_Int_Var записей, принадлежащих к типу Record_Type.

Интересным примером использования обобщенных ссылочных типов может служить следующее схематическое описание пакета:



package Message_Services is

type Message_Code_Type is range 0..100;

subtype Message is String;

function Get_Message(Message_Code: Message_Code_Type) return Message;

pragma Inline(Get_Message); end Message_Services;

package body Message_Services is

type Message_Handle is access constant Message;

Message_0: aliased constant Message := "OK"; Message_1: aliased constant Message := "Up"; Message_2: aliased constant Message := "Shutdown"; Message_3: aliased constant Message := "Shutup"; . . .

Message_Table: array (Message_Code_Type) of

Message_Handle := (0 => Message_0'Access, 1 => Message_1'Access, 2 => Message_2'Access, 3 => Message_3'Access, . . . );

function Get_Message(Message_Code: Message_Code_Type) return Message is

begin

return Message_Table(Message_Code).all; end Get_Message; end Message_Services;

В данном случае, достаточно элегантным приемом является использование массива Message_Table, который представляет таблицу ссылок на строковые константы переменной длины. Следует также заметить, что при этом не производится никакого распределения пространства в области динамической памяти.


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