Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 53
Текст из файла (страница 53)
Область видимости ...х... епс)г ( 5ОЬ1 ) ргоаес)иге вцЬ2; чаг х : 1пгедег; Ьеа1п ( вцЬ2 епс(; ( виЬ2 ! Ьедйа ( Ь1ц (г (Ь1д) При использовании статического обзора данных ссылка на переменную х полпрограммы виЬ1 относится к переменной х, объявленной в процедуре Ь1д. Это действительно так, поскольку поиск обьявления переменной х начался в той процедуре, в которой встречается ссылка, но объявления этой переменной в ней найдено не было. Далее поиск продолжился в статическом родителе подпрограммы вцЬ1 (подпрограмме Ь1д), в котором и было найдено объявление переменной х.
Наличие предопределенных имен, рассмотренных в разделе 4.2.3, несколько затрудняет описанный процесс. Иногда предопределенное имя подобно ключевому слову и может переопределяться пользователем. В таких случаях предопределенное нмя используется, только если пользовательская программа не содержит переопределения. В других случаях предопределенное имя может быть зарезервировано, что означает начало поиска значения данного имени в списке предопределенных имен, который выполняется даже до проверки объявлений локальной области видимости.
В языках со статическим обзором данных объявления некоторых переменных могут быть скрыты от некоторых подпрограмм. Рассмотрим следующую скелетную программу на языке Рааса!: ргоагаа п~а1пг чаг х : 1пгедег) ргоаейиге виЬ1; чаг х : 1пгеаег) Ьеяз.п ( вцЬ1 ...х... епа) ( виЬ1 Ьеа1п (жа1п) епс$. (та1п) Ссылка на переменную х в процелуре вцЬ1 относится к объявившей переменную х процедуре вцЬ1.
В этом случае переменная х программы жа1п скрыта от команд процедуры вцЬ1. Вообще, объявление переменной эффективно скрывает любое объявление одноименной переменной, содержащейся во внешней области видимости. В языке Ада к переменным. скрытым от областей видимостей предков, можно получить доступ с помощью селективных ссылок, содержащих имя области видимости предка. В прелылущей программе, например, к переменной х процедуры вцЬ1 можно обратиться с помощью ссылки п~а1п.
х. Несмотря на то что в языках С и С++ не разрешено использование надира~рамы, вложенных в определения других подпрограмм, глобальные переменные в этих языках есть. Эти переменные объявляются вне определения любой подпрограммы. Как и в язы- Глава 4. Имена, связывание, проверка типов н области видимости ке Рааса), локальные переменные могут скрывать эти глобальные переменные. В языке С++ к таким скрытым глобальным переменным можно обращаться с помощью оператора доступа (:: ).
Например. если переменная х является глобальной переменной, скрытой в подпрограмме локальной переменной х. то обратиться к глобальной переменной можно в форме:: х. Я.8.2. Блоки Многие языки позволяют создавать новые статические области вилимости во время выполнения программы. Эта мощная концепция, впервые появившаяся в языке А].ОО[. 60, позволяет фрагменту программы иметь собственные локальные переменные с минимизированной областью видимости.
Подобные переменные, как правило. являются автоматическими, так что память выделяется им в начале выполнения фрагмента программы, а освобождается по окончании его выполнения. Подобный фрагмент программного кода получил название блока (Ыосй). Как показано ниже, в языке Ада блоки задаются оператором с)ео1вке: с(еа1акв ТЕМР : ЕпСеоегз Ьеадп ТЕМР := ГТКЯТг Г1КБТ := ЕЕООМО; 5ЕСО))О := ТЕМР; аг От понятия "блок' произошло выражение язык е блочной структурой (Ыос[ссцгцсшгед )апйоайе). Хотя языки Рааса) и Мог)ц[а-2 и называются языками с блочной структурой. они не имеют непроцедурных блоков.
В языках С, С: ~ и )ача любой составной оператор (последовательности операторов, заключенной в фигурные скобки) может содержать объявления и таким образом определять новую область видимости. Такие составные операторы являются блоками. Например, если 11 я с — массив целых чисел, то можно написать следующий код: И (11яс[1] < 1зяс[1]) ( йпс сетрг сеп|р - 11я [1]; 115с [1] = 1" яс [1] 11яс [1] = Сежр; ) Области видимости, созлаваемые блоками, трактуются точно так же, как области видимости, создаваемые подпрограммами.
Обращения к переменным блока. не объявляемым в этом блоке, связываются с их обьявлениями путем поиска по возрастающей во внешних областях. В языках Сн и Зача опрелелять переменные можно в любом месте функции. Если определение появляется не в начале функции, то область видимости данной переменной начинается с оператора определения и заканчивается концом функции. Оператор Гок языков С++ и )ача позволяет определять переменные в выражениях, инициализирующих счетчики цикла. В ранних версиях языка С++ область видимости такой переменной начиналась с ее определения и заканчивалась в конце наименьшего бло- 4.8.
Область видимости ка. содержащего данную переменную. Впрочем, в предварительной станлартной версии область видимости таких переменных была ограничена телом цикла кок, так же пас ~ ~- пили и в языке Зата. Определения класса и метода в объектно-ориентированных языках программирования также порождают вложенные статические области видимости. Этот вопрос рассмап ривается в главе! 1. 4.8.3. Оценка статического обзора данных Использование статических областей вилимости представляет собой метод нелокального доступа, хорошо работающий во многих ситуациях.
Впрочем, у этого метода есть и недостатки. Рассмотрим программу, скелетная структура которой показана на рис. 4.1. При этом булем считать, что все области видимости созлаются опрелелениями основной программы и процелур. Программа содержит общую область видимости лля блока вази. помимо этого существуют две процедуры й и В, определяющие области видимости внутри блока мазо. Внутри процедуры А расположены области видимости процедур С и В. Внутри процедуры В находится область видимости процедуры Е. Мы предполагаем, что необходимое обращение к данным и процедурам определяется структурой рассматриваемой программы.
Требуемое обращение к процедуре имеет следующий вид; программа вазп может вызывать блоки А и В. блок й — блоки С и В, а блок  — блоки А и Е. Структуру программы удобно представить в виде дерева, каждый узел которого представляет процедуру и, следовательно, область видилюсти. Представление программы, показанной на рис. 4.1, изображено на рис. 4.2. Структура этой программы может показаться весьма естественной организацией программы, отчетливо отражающей структурные требования. Впрочем, изображенный на рис. 4.3 граф возможных вызовов процедур этой программы показывает, что возможно значительно большее количество вызовов, чем необходимо. Г Рис. 4.1.
Структура праграиты Рис. 4.2. Древовидная структура праграимы, показанной иа рис. 4.1 196 Глава 4. Имена, связывание, проверка типов и области видимости На рис. 4.4 показаны требуемые вызовы рассматриваемой программы. Различия между рис. 4.3 и 4.4 показывают число возможных. а не необхолиьгых вызовов. Программист люжет по ошибке вызвать подпрограмму. вызов которой не лолжен допускаться, причем это действие не бчлет расценено колгпилятором как ошибка.
В результате ошибка булет обнаружена только при выполнении программы. что может повысить стоимость ее исправления. Следовательно, доступ к процедурам должен быть ограничен только необхолимымн процедурами. авен Рас. 4.3. Гриф оызоноо, возчожных о проерачзие, показанной ни рнс. 4. 1 Рис. 4.4. Граф вызооон, необходипых дол проеракогы, изображенной на рнс. 4.
1 191 4.8. Область видимости С этой проблемой связано слишком интенсивное обрашенйе к данным. Например, все переменные, объявленные в основной программе. видимы лля всех процелур. причем избежать этого невозможно. Следующий сценарий описывает другие проблемы. возникающие при использовании статического обзора данных. Предположим. что после разработки и тестирования программы потребовалось изменить ее спецификацию. В частности. необходимо открыть процедуре Е поступ к некоторым переменным из области видимости процедуры Е. Для того чтобы решить возникшую проблему, можно переместить процедуру Е внутрь области видимости процедуры В.
Однако в этом случае процедура Е уже не сможет обращаться к области вилимости процедуры В, что, по-видимому. требуется(иначе зачем она там находится?). Другим решением является перемещение переменных. определяемых в процедуре й и необходимых в процедуре Е, в блок жахп, Это позволит обращаться к этим переменным из любой процедуры, которых может оказаться больше, чем надо, что может спровоцировать некорректный доступ. Например.
неверно написанный идентификатор процедуры может быть воспринят не как ошибка, а как ссылка на идентификатор в некоторой внешней области вилимости. Предположим, что переменная, перемещенная в блок жазп, называется х и необходима в процедурах 0 и Е. Допустим, что переменная с таким же именем объявляется в процедуре А. Это привелет к сокрытию требуемой переменной х от ее изначального владельца — процедуры В. Последней проблемой.
возникающей при перемещении объявления переменной х в блок жазп, является пагубное влияние этого действия на читабельность, выражающееся в том, что объявления переменных находятся слишком далеко от места их использования. Проблемы, связанные с видимостью переменных при использовании статических областей видимости, характерны и для обрашений к подпрограммам. Предположим, что а программе, изображенной на рис.
4.2, вследствие некоторых изменений спецификации возникла потребность вызова процедурой Е процедуры О. Чтобы это стало возможным. следует вложить процедуру (э непосредственно в блок па 8п, предполагая, что эта процедура также требуется процедурам А или С. При этом перемешении процедура () теряет доступ к переменным, определенным в процедуре А. Этот способ решения проблемы. если использовать его часто, приведет к возникновению программ с длинными списками служебных процедур низкого уровня.