Область видимости : локальная, глобальная, внутри класса

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

Язык С++ поддерживает следующие области видимости:
  • локальная область видимости;
  • область видимости класса;
  • пространство имен;
  • область видимости файла.
Область видимости файла включает в себя вышеперечисленные области.

Локальная область видимости

Локальная область видимости – это область видимости внутри блока.

Каждая функция – это отдельная область видимости. Внутри функции может быть несколько блоков, заключенных в фигурные скобки {…}, также образующих отдельные области видимости. Для переменных, объявленных в блоке, область видимости – от точки объявления до конца блока.

 
 
 
 
 
for (int i = 0; i<10; i++)
{
  тело цикла;
}
// переменная i недоступна

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

Каждый класс представляет отдельную область видимости. Имена членов класса локальны в этом классе. Область видимости полей и методов класса (член-данных и член-функций) не зависит от точки их объявления, то есть член класса виден во всем классе. Каждый метод определяет свою собственную локальную область видимости, аналогично обычной функции. Можно явно указать область видимости в С++, используя оператор разрешения контекста (области видимости) ::.

Оператор разрешения контекста имеет самый высокий приоритет и применяется в двух формах:

  • унарная — ссылается на внешний контекст;
  • бинарная — ссылается на контекст класса.

Унарная форма записи:

:: Идентификатор

Бинарная форма записи:

ИмяКласса :: Идентификатор

Унарная форма используется для обращения к имени, относящемуся ко внешнему контексту и скрытому локальным контекстом или контекстом класса.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
int count = 0; // (*)
void func(void
{
  for (int count = 0; count < 10; count++) 
  {
    ++ ::count;  // увеличивает на 1 (*)
  }
}
int main() 
{
  cout << "count =" << ::count << endl;
  func();
  cout << "count =" << ::count << endl;
  cin.get();
  return 0;
}

Результат выполнения

Область видимости переменной

Бинарная форма используется для ссылки на контекст класса с целью устранения неоднозначности имен, которые могут повторно использоваться внутри класса.

1
2
3
4
class cl1 {void f() {…} …};
class cl2 {void f() {…} …};
cl1 :: f();  // обращение к f() из cl1
cl2 :: f();  // обращение к f() из cl2

Классы могут быть вложенными. Правила видимости для вложенных классов рассмотрим на примере.

Пример

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;
int c;  // внешняя область (контекст)
class X  // внешнее объявление класса
{
public:
  static int c;
  class Y  // внутренне объявление класса
  {
    public:
      static int c;
      static void f(int key) 
      {
        ::c = key;      // внешняя переменная
        X::c = key + 1; // переменная c класса X
        c = key + 2;    // переменная c класса Y
      }
  };
};
int X::c = 0;
int X::Y::c = 0;
int main() 
{
  X::Y::f(3);
  cout << "   c = " << c << endl;
  cout << "X::c = " << X::c << endl;
  cout << "Y::c = " << X::Y::c << endl;
  cin.get();
  return 0;
}

Результат выполнения

С++ дает возможность создавать вложенные методы с использованием вложенных классов. Это ограниченная форма вложенности функций. Методы должны определяться внутри локального класса, и на них нельзя ссылаться внутри этого контекста. Как и в Си, обычные вложенные функции запрещены. Вложенный класс не находится в области действия включающего его класса.

Пространства имен

Области видимости могут быть вложенными.

Для разделения областей видимости используются так называемые пространства имен.

Пространство имён (namespace) — это некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (имен).

Объявление пространства имен имеет синтаксис:

 
 
 
 
namespace Идентификатор
{
  Содержимое
}
Пример
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
int X = 100;   // глобальное пространство имен
namespace A    // пространство имен A
{
  int X = 10;
  namespace B  // пространство имен B
  {
    int X = 20;
  }
}
int main() {
  int X = 1;
  cout << "X = " << X << endl;
  cout << "A::X = " << A::X << endl;
  cout << "A::B::X = " << A::B::X << endl;
  cout << "::X = " << ::X << endl;
  cin.get();
  return 0;
}

Результат выполнения
Прокрутить вверх