Бьерн Страуструп - Язык программирования С++. Главы 2-4
Страница 3. Область видимости



2.1.1  Область видимости

Описанием определяется область видимости имени. Это значит, что
имя может использоваться только в определенной части текста программы.
Если имя описано в функции (обычно его называют "локальным именем"), то
область видимости имени простирается от точки описания
до конца блока, в котором появилось это описание. Если имя не находится
в описании функции или класса (его обычно называют "глобальным именем"),
то область видимости простирается от точки описания до конца файла,
в котором появилось это описание.
Описание имени в блоке может скрывать описание в объемлющем блоке или
глобальное имя; т.е. имя может быть переопределено так, что оно будет
обозначать другой объект внутри блока. После выхода из блока прежнее
значение имени (если оно было) восстанавливается. Приведем пример:

int x;            // глобальное x

void 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;

   void f2()
   {
     int x = 1;      // скрывает глобальное x
     ::x = 2;        // присваивание глобальному x
   }

  Возможность использовать скрытое локальное имя отсутствует.
  Область видимости имени начинается в точке его описания (по
окончании описателя, но еще до начала инициализатора - см. $$R.3.2). Это
означает, что имя можно использовать даже до того, как задано его
начальное значение. Например:

   int x;

   void f3()
   {
      int x = x;    // ошибочное присваивание
    }

 Такое присваивание недопустимо и лишено смысла. Если вы попытаетесь
 транслировать эту программу, то получите предупреждение: "использование
 до задания значения". Вместе с тем, не применяя оператора ::, можно
 использовать одно и то же имя для обозначения двух различных объектов
 блока. Например:

    int x = 11;

    void f4()         // извращенный пример
    {
      int y = x;   //  глобальное x
      int x = 22;
      y = x;       // локальное x
    }

 Переменная y инициализируется значением глобального x, т.е. 11,
 а затем ей присваивается значение локальной переменной x, т.е. 22.
 Имена  формальных параметров функции считаются описанными в самом
 большом блоке функции, поэтому в описании ниже есть ошибка:

    void f5(int x)
    {
      int x;       // ошибка
     }

 Здесь x определено дважды в одной и той  же  области видимости.
 Это хотя и не слишком редкая, но довольно тонкая ошибка.

 
« Предыдущая статья   Следующая статья »