Имена параметров функции vec и val принадлежат к первой локальной области видимости тела функции, и в ней использовать те же имена для других сущностей нельзя. Например:
int binSearch( const vectorint vec, int val )
{ // локальная область видимости: уровень #1
int val; // ошибка: неверное переопределение val
// ...
Имена параметров употребляются как внутри тела функции binSearch(), так и внутри вложенной области видимости цикла while. Параметры vec и val недоступны вне тела функции binSearch().
Разрешение имени в локальной области видимости происходит следующим образом: просматривается та область, где оно встретилось. Если объявление найдено, имя разрешено. Если нет, просматривается область видимости, включающая текущую. Этот процесс продолжается до тех пор, пока объявление не будет найдено либо не будет достигнута глобальная область видимости. Если и там имени нет, оно будет считаться ошибочным.
Из-за порядка просмотра областей видимости в процессе разрешения имен объявление из внешней области может быть скрыто объявлением того же имени во вложенной области. Если бы в предыдущем примере переменная low была объявлена в глобальной области видимости перед определением функции binSearch(), то использование low в локальной области видимости цикла while все равно относилось бы к локальному объявлению, скрывающему глобальное:
int low;
int binSearch( const vectorint vec, int val )
{
// локальное объявление low
// скрывает глобальное объявление
int low = 0;
// ...
// low - локальная переменная
while ( low = high )
{//...
}
// ...
}
Для некоторых инструкций языка C++ разрешено объявлять переменные внутри управляющей части. Например, в цикле for переменную можно определить внутри инструкции инициализации:
for ( int index = 0; index vecSize; ++index )
{
// переменная index видна только здесь
if ( vec[ index ] == someValue )
break;
}
// ошибка: переменная index не видна
if ( index != vecSize ) // элемент найден
Подобные переменные видны только в локальной области самого цикла for и вложенных в него (это верно для стандарта С++, в предыдущих версиях языка поведение было иным). Компилятор рассматривает это объявление так же, как если бы оно было записано в виде:
// представление компилятора
{ // невидимый блок
int index = 0;
for ( ; index vecSize; ++index )
{
// ...
}
}
Тем самым программисту запрещается применять управляющую переменную вне локальной области видимости цикла. Если нужно проверить index, чтобы определить, было ли найдено значение, то данный фрагмент кода следует переписать так:
int index = 0;
for ( ; index vecSize; ++index )
{
// ...
}
// правильно: переменная index видна
if ( index != vecSize ) // элемент найден
Поскольку переменная, объявленная в инструкции инициализации цикла for, является локальной для цикла, то же самое имя допустимо использовать аналогичным образом и в других циклах, расположенных в данной локальной области видимости:
void fooBar( int *ia, int sz )
{
for (int i=0; isz; ++i) ... // правильно
for (int i=0; isz; ++i) ... // правильно, другое i
for (int i=0; isz; ++i) ... // правильно, другое i
}
Аналогично переменная может быть объявлена внутри условия инструкций if и switch, а также внутри условия циклов while и for. Например:
if ( int *pi = getValue() )
{
// pi != 0 -- *pi можно использовать здесь
int result = calc(*pi);
// ...
}
else
{
// здесь pi тоже видна
// pi == 0
cout "ошибка: getValue() завершилась неудачно" endl;
}
Переменные, определенные в условии инструкции if, как переменная pi, видны только внутри if и соответствующей части else, а также во вложенных областях. Значением условия является значение этой переменной, которое она получает в результате инициализации. Если pi равна 0 (нулевой указатель), условие ложно и выполняется ветвь else. Если pi инициализируется любым другим значением, условие истинно и выполняется ветвь if. (Инструкции if, switch, for и while рассматривались в главе 5.)
Найдите различные области видимости в следующем примере. Какие объявления ошибочны и почему?
int ix = 1024;
int ix() ;
void func( int ix, int iy ) {
int ix = 255;