Функции в качестве параметров подпрограмм
«Любой дурак может написать программу, которую поймет компилятор. Хорошие программисты пишут программы, которые смогут понять другие программисты»
20. Параметры подпрограмм
Список формальных параметров подпрограммы определяет число, порядок и тип фактических параметров, которые д.б. указаны при вызове подпрограммы.
Формальные параметры можно классифицировать на следующие виды: параметры значения, переменные, константы и выходные (var, const и out).
Параметры-значения всегда имеют тип, т.е. являются типизированными, в то время как все другие могут быть типизированными или нетипизированными. Кроме того, специфические правила применяются к параметрам массивам.
Файловые переменные и структурные типы, включающие файловые типы, должны всегда объявляться как параметры переменные.
Параметры переменные и параметры значения.
Параметры значения передаются как значения, в то время как параметры переменные передаются по ссылке (reference). Для пояснения различия между ними сравните две функции:
function DoubleByValue(X: Integer): Integer; // X is a value parameter
function DoubleByRef(var X: Integer): Integer; // X is a variable parameter
Эти функции возвращают одинаковые значения, однако вторая изменяет значение соответствующего фактического параметра:
var I, J, V, W: Integer;
J := DoubleByValue(I); // J = 8, I = 4
W := DoubleByRef(V); // W = 8, V = 8
Даже если одна и та же переменная используется как два или более параметров, никаких копий не создается, например:
procedure AddOne(var X, Y: Integer);
Фактический параметр, соответствующий параметру переменной, должен быть сущностью, которой можно присвоить значение: переменной, типизированной константой, разыменованным указателем, полем или индексированным именем массива.
Эти параметры подобны параметрам значениям за тем исключением, что их значения нельзя изменять в подпрограмме. Их нельзя также передавать (внутри подпрограммы) другим подпрограммам как параметры переменные. Вместе с тем, когда передается ссылка на объект (как параметр константа), свойства объекта модифицировать можно.
Использование параметров констант позволяет компилятору оптимизировать код для строковых и структурных параметров. Кроме того, это обеспечивает также защиту от непредумышленной передачи параметра другой подпрограмме в качестве параметра переменной.
Эти параметры (out parameters), подобно параметрам переменным, также передаются по ссылке. Вместе с тем начальное значение выходного параметра игнорируется, так как он предназначен только для возврата результата. Например,
procedure GetInfo(out Info: SomeRecordType);
При вызове этой процедуры ей передается некоторая переменная типа SomeRecordType и она не используется для передачи каких-либо данных процедуре. Выходные параметры часто используются при использовании COM и CORBA моделей. Кроме того, параметр необходимо объявлять выходным, если процедуре передается неинициализированная переменная.
Любой из параметров – var, const или out – может быть объявлен как не имеющий типа, т.е. нетипизированный. Исключение составляет лишь параметр значение, тип которого должен быть указан обязательно. Пример:
procedure TakeAnything(var A; const B; out C);
Если параметр объявлен нетипизированным, соответствующий фактический параметр не может быть числом или нетипизированной числовой константой. Внутри подпрограммы нетипизированный параметр несовместим ни с каким типом и для его использования необходимо обязательно выполнять приведение типа (typecast).
Приведенная ниже функция иллюстрирует использование нетипизированных параметров для того, чтобы выполнять сравнение параметров любых типов:
Function Equal(var Source, Dest; Size: Integer): Boolean;