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

       

Ссылочные типы для подпрограмм


Также как и обобщенные ссылочные типы, ссылочные типы для подпрограмм не доступны в стандарте Ada83.

Они являются нововведением, которое определил выход стандарта Ada95.

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

При описании ссылочных типов для подпрограмм следует придерживаться следующих соглашений:

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

  • при описании ссылочного типа для функции, тип возвращаемого значения должен соответствовать типу возвращаемого значения функции на которую будут ссылаться значения этого типа

  • переменные ссылочного типа для подпрограмм могут быть использованы для доступа к любой подпрограмме профиль которой соответствует профилю определеному при описании этого ссылочного типа

    Простейшим примером использования функционального ссылочного типа как параметра подпрограммы может служить следующий фрагмент кода:

    type Access_Function is access function(Item: in Float) return Float;

    type Vector is array (Integer range < >) of Float;

    procedure For_Each( F : in Access_Function; To: in out Vector ) is

    begin

    for I in To'Range loop

    To(I) := F( To(I) ); end loop; end For_Each;

    Здесь, процедура For_Each принимает в качестве параметра F

    значение ссылочного типа Access_Function указывющее на функцию, которую необходимо вызывать при обработке каждого элемента массива типа Vector, передаваемого ей как параметр To.

    Примечательно, что при вызове функции F расшифровка ссылки производится автоматически. Следует также заметить, что вместо "F( To(I) )" можно было бы написать "F.all( To(I) )", что в подобных случаях - не обязательно.

    Использование .all требуется когда вызываемая подпрограмма (процедура или функция) не имеет параметров.




    Описание переменной массива чисел, передаваемой как параметр To для процедуры For_Each, и описание функции, ссылка на которую могла бы быть использовна как параметр F процедуры For_Each, могут иметь следующий вид:

    Data_Vector : Vector (1..3) := (1.0, 2.0, 3.0);

    function Square(Val: in Float) return Float is

    begin

    return Val * Val; end Square;

    Таким образом, вызов процедуры For_Each (с учетом приведенных ранее описаний) будет иметь вид:

    For_Each( F => Square'Access, To => Data_Vector );

    Примечательно, что для получения ссылочного значения которое указывает на функцию Square используется атрибут 'Access.

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

    type Action_Operation is access procedure;

    procedure Add; procedure List; procedure Delete;

    Action : constant array (1..3) of Action_Operation := ( Add'Access, List'Access, Delete'Access

    );

    type Math_Function is access function (I : in Float) return Float;

    function Sin (F : in Float) return Float; function Cos (F : in Float) return Float; function Tan (F : in Float) return Float;

    Math_Operation : constant array (1..3) of Math_Function := ( Sin'Access, Cos'Access, Tan'Access

    );

    Здесь формируются две таблицы вызовов подпрограмм: первая таблица вызовов представлена массивом Action, который содержит значения ссылочного типа Action_Operation, а вторая таблица вызовов представлена массивом Math_Operation, который содержит значения ссылочного типа Math_Function

    (заметим, что таблицами вызовов, как правило, являются массивы).

    Примером вызова I-той подпрограммы в таблице (где I - это индекс в таблице) может служить следующее:

    F: Float; . . .

    Action(I).all; -- вызов I-той процедуры из таблицы -- Action F := Math_Operation(I)(F); -- вызов I-той функции из таблицы -- Math_Operation с параметром F

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


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