В разделе описания подпрограмм допускается вложенность подпрограмм.
На рис. 3.8. схематично представлена структура программы с вложенными подпрограммами.
Далее представлен пример описания процедур для программы с такой структурой.
Рис. 3.8.Структура программы с вложенностью подпрограмм
ProgramStructureExample;
ProcedureA;
Begin
end;{A}
Procedure B;
ProcedureBl;
Begin
end;{Bl}
ProcedureB2;
ProcedureB21;
Begin
end;{B2l}
ProcedureB22
Begin
end;{B22}
Begin
end;{B2}
Begin
end;{B}
Begin
end.{Program}
Подпрограмма любого уровня имеет обычно множество имен констант, переменных, типов и вложенных в нее подпрограмм низшего уровня.
Все имена, описанные внутри подпрограммы, локализуются в ней, т.е. они “невидимы” снаружи подпрограммы. Таким образом, со стороны операторов; использующих обращение к подпрограмме, она трактуется как внешний «черный ящик», в котором реализуется тот или иной алгоритм. Все детали этой реализации «скрыты» от программы и недоступны ей.
Например, в рассмотренном выше примере из основной программы можно обратиться к процедурам A и B, но нельзя вызвать ни одну из вложенных в подпрограмму B процедур: B1, B2, B21, B22.
Это относится не только к именам самих подпрограмм, но и вообще к любым объявленным в них именам - типам, константам, переменным и меткам. Все имена в пределах подпрограммы, в которой они объявлены, должны быть уникальными и не могут совпадать с именем самой подпрограммы.
При входе в подпрограмму низшего уровня становятся доступными не только объявленные в ней имена, но и сохраняется доступ ко всем именам верхнего уровня. Образно говоря, любая подпрограмма как бы окружена полупрозрачными стенками: снаружи подпрограммы не видны ее внутренности, но, попав в подпрограмму, можно наблюдать все, что делается снаружи.
Так, в рассмотренном примере, из подпрограммы B21 можно вызвать подпрограмму A, использовать имена, объявленные в основной программе, в подпрограммах B и B2, и даже обратиться к ним.
Более того, любая подпрограмма может вызывать саму себя – такой
способ вызова называется рекурсией. Рекурсия рассмотрена в разделе 3.15.6.
При взаимодействии подпрограмм одного уровня иерархии вступает в силу основное правило Object Pascal: любая подпрограмма перед ее использованием должна быть описана.
Таким образом, в рассмотренном примере, из подпрограммы B можно вызвать подпрограмму A, но из A вызвать B невозможно. Для такой возможности необходимо использовать опережающее описание подпрограмм (см. раздел 3.15.7.)
Объекты (переменные, константы, типы, подпрограммы), описанные
на верхнем от данной подпрограммы уровне и доступные в ней, называются глобальными по отношению для данной подпрограммы.
Объекты, описанные в данной подпрограмме и доступные в ней и в подпрограммах более низкого уровня, называются локальными для данной подпрограммы.
Локализованные в подпрограмме имена могут совпадать с ранее объявленными глобальными именами. В этом случае считается, что локальное имя «закрывает» глобальное и делает его недоступным, например:
Var
i : Integer;
ProcedureStudentEx;
Var
i : Integer; {описание локальной переменной}
Begin
i:=3;
writeln(i);
end{ StudentEx };
Begin
i:=1;
StudentEx;
end;
На экран будет выведено значение 3. Глобальной переменной i в теле программы присвоено значение 1, однако, в процедуре StudentEx объявлена локальная переменная с таким же именем i. Поэтому в процедуре StudentEx используется именно локальная переменная i со значением 3.
Следует заметить, что если из процедуры StudentEx убрать описание переменной i: