Область Видимости
Описание вводит имя в области видимости; то есть, имя может использоваться только в определенной части программы. Для имени, описанного в функции (такое имя часто называют локальным), эта область видимости простирается от точки описания до конца блока, в котором появилось описание; для имени не в функции и не в классе (называемого часто глобальным именем) область видимости простирается от точки описания до конца файла, в котором появилось описание. Описание имени в блоке может скрывать (прятать) описание во внутреннем блоке или глобальное имя. Это значит, что можно переопределять имя внутри блока для ссылки на другой объект. После выхода из блока имя вновь обретает свое прежнее значение. Например:
int x; // глобальное x
f() { int x; // локальное x прячет глобальное x x = 1; // присвоить локальному x { int x; // прячет первое локальное x x = 2; // присвоить второму локальному x } x = 3; // присвоить первому локальному x }
int* p = x // взять адрес глобального x
Скрытие имен неизбежно при написании больших программ. Однако читающий человек легко может не заметить, что имя скрыто, и некоторые ошибки, возникающие вследствие этого, очень трудно обнаружить, главным образом потому, что они редкие. Значит скрытие имен следует минимизировать. Использование для глобальных переменных имен вроде i или x напрашивается на неприятности.
С помощью применения операции разрешения области видимости :: можно использовать скрытое глобальное имя. Например:
int x;
f() { int x = 1; // скрывает глобальное x ::x = 2; // присваивает глобальному x }
Но возможности использовать скрытое локальное имя нет.
Область видимости имени начинается в точке описания. Это означает, что имя можно использовать даже для задания его собственного значения. Например:
int x;
f() { int x = x; // извращение }
Это не является недопустимым, хотя и бессмысленно, и компилятор предупредит, что x "used before set" ("использовано до того, как задано"), если вы попробуете так сделать. Можно, напротив, не применяя операцию ::, использовать одно имя для ссылки на два различных объекта в блоке. Например:
int x;
f() // извращение { int y = x; // глобальное x int x = 22; y = x; // локальное x }
Переменная y инициализируется значением глобального x, 11, а затем ему присваивается значение локальной переменной x, 22.
Имена параметров функции считаются описанными в самом внешнем блоке функции, поэтому
f(int x) { int x; // ошибка }
содержит ошибку, так как x определено дважды в одной и той же области видимости.
Есть четыре вида областей видимости: локальная, файл, программа и класс.
Локальная: | Имя, описанное в блоке (), локально в этом блоке и может использоваться только в нем после места описания и в охватываемых блоках. Исключение составляют метки (#9.12), которые могут использоваться в любом месте функции, в которой они описаны. Имена формальных параметров функции рассматриваются так, как если бы они были описаны в самом внешнем блоке этой функции. |
Файл: | Имя, описанное вне любого блока () или класса (), может использоваться в файле, где оно описано, после места описания. |
Класс: | Имя члена класса локально для его класса и может использоваться только в функции члене этого класса (#8.5.2), после примененной к объекту его класса () операции . или после примененной к указателю на объект его класса () операции -. На статические члены класса () и функции члены можно также ссылаться с помощью операции :: там, где имя их класса находится в области видимости. Класс, описанный внутри класса (), не считается членом, и его имя принадлежит охватывающей области видимости. |
Имя может быть скрыто посредством явного описания того же имени в блоке или классе. Имя в блоке или классе может быть скрыто только именем, описанным в охватываемом блоке или классе. Скрытое нелокальное имя также может использоваться, когда его область видимости указана операцией :: (#7.1). Имя класса, скрытое именем, которое не является именем типа, все равно может использоваться, если перед ним стоит class, struct или union (). Имя перечисления enum, скрытое именем, которое не является именем типа, все равно может использоваться, если перед ним стоит enum ().