Областьвидимостикласса
Классы привносят новые правила определения области видимости (scope) в дополнение к существующим в ядре языка С. Одна из целей, преследуемых при использовании классов – обеспечить применение техники инкапсуляции. Это означает, что все имена, объявленные внутри класса, должны трактоваться внутри их собственного пространства имен, в отличие от внешних имен, имен функций и имен других классов. Появляется потребность в ведении оператора разрешения области видимости (scope resolution).
Оператор разрешения области видимости ::
Оператор разрешения области видимости является оператором самого высокого приоритета в языке. Он может принимать две формы:
:: i // унарный оператор – указывает
// на внешнюю область видимости
foo_bar // бинарный оператор – указывает
// на область видимости класса
Унарная форма используется для того, чтобы раскрыть имя (получить к нему доступ), которое имеет внешнюю область видимости и было скрыто объявлением в локальной области видимости или в области видимости класса:
int count = 0; //внешняя переменная
void how_many (double w[ ], double х, int& count)
{
for (int = 0; i < N; ++i)
count += (w[i] = = x);
++ :: count;
}
Бинарная форма используется для того, чтобы устранить неоднозначность в именах, которые повторно используются в пределах класса, как показано ниже. Позже мы будем применять ату форму с наследованием и пространствами имен.
class widgets { public: void f ( ); };
class gizmos { public. void f ( ); };
void f() {/*что-нибудь*/} //просто внешняя функция f
void widgets :: f() {/*что-нибудь*/} // f с областью видимости
// widgets
void gizmos :: f() {/*что-нибудь*/} //f с областью видимости
//gizmos
Можно представить себе оператор разрешения области видимости, как то, что указывает путь к конкретному идентификатору. Отсутствие модификатора области видимости означает, что применяются обычные правила видимости имен.
Продолжая предыдущий пример:
widgets w;
gizmos g;
g. f ( );
w.f ( );
g.gizmos :: f ( ); //верно и избыточно
g.widgets :: f ( ); //неверно, widgets :: f ( ) не может
//действовать на gizmos
Вложенные классы
Классы, также как блоки и пространства имен, могут быть вложены. Области видимости и вложенность позволяют локально скрывать имена и выделять ресурсы. Часто случается, что класс нужен как часть реализации некой большей конструкции.
char с; //внешняя область видимости ::с
class Х { //объявление объемлющего класса Х ::
char с; //Х :: с
public:
class Y{ //объявление вложенного класса Х ::Y::
public:
void foo (char е) {Х t; ::с = t.Х::с = с = e;}
private:
char с; //X :: Y :: c
};
};
В классе Y функция-член foo ( ), используя :: с, ссылается на глобальную переменную с; используя X :: с, ссылается на переменную объемлющего класса; используя с, ссылается на переменную Х :: У :: с вложенного класса. Все три переменные с именем с доступны при использовании оператора разрешения области видимости.
Более того, классы с чисто локальной областью видимости могут создаваться внутри блоков. Их определения недоступны вне контекста соответствующих блоков.
void foo ( )
{
class local {..... } x; //что-нибудь
}
local у; //неверно: local виден
//только внутри foo ( )
Отметим, что С ++ позволяет вкладывать определения функций, используя вложение классов. Это ограниченная форма вложения функций. Функции-члены должны быть определены внутри локального класса и на них нельзя ссылаться вне его области видимости. Как и в С, простое вложение функций недопустимо.