13.10.1. Разрешение имен в области видимости вложенного класса

13.10.1. Разрешение имен в области видимости вложенного класса

Посмотрим, как разрешаются имена в определениях вложенного класса и его членов.

Имя, встречающееся в определении вложенного класса (кроме тех, которые употребляются во встроенных функциях-членах и аргументах по умолчанию) разрешается следующим образом:

* Просматриваются члены вложенного класса, расположенные перед употреблением имени.

* Если шаг 1 не привел к успеху, то просматриваются объявления членов объемлющего класса, расположенные перед употреблением имени. Если и этого недостаточно, то просматриваются объявления, расположенные в области видимости пространства имен перед определением вложенного класса.

Например:

enum ListStatus { Good, Empty, Corrupted };

class List {

public:

// ...

private:

class ListItem {

public:

// Смотрим в:

// 1) List::ListItem

// 2) List

// 3) глобальной области видимости

ListStatus status; // относится к глобальному перечислению

// ...

};

// ...

};

Сначала компилятор ищет объявление ListStatus в области видимости класса ListItem. Поскольку его там нет, поиск продолжается в области видимости List, а затем в глобальной. При этом во всех трех областях просматриваются только объявления, предшествующие использованию ListStatus. В конце концов находится глобальное объявление перечисления ListStatus – оно и будет типом, использованным в объявлении status.

Если вложенный класс ListItem определен в глобальной области видимости, вне тела объемлющего класса List, то все члены List уже были объявлены:

class List {

private:

class ListItem {

//...

public:

enum ListStatus { Good, Empty, Corrupted };

// ...

};

class List::ListItem {

public:

// Смотрим в:

// 1) List::ListItem

// 2) List

// 3) глобальной области видимости

ListStatus status; // относится к глобальному перечислению

// ...

};

При разрешении имени ListStatus сначала просматривается область видимости класса ListItem. Поскольку там его нет, поиск продолжается в области видимости List. Так как полное определение класса List уже встречалось, просматриваются все члены этого класса. Вложенное перечисление ListStatus найдено несмотря даже на то, что оно объявлено после объявления ListItem. Таким образом, status объявляется как указатель на данное перечисление в классе List. Если бы в List не было члена с таким именем, поиск был бы продолжен в глобальной области видимости среди тех объявлений, которые предшествуют определению класса ListItem.

Имя, встретившееся в определении функции-члена вложенного класса, разрешается следующим образом:

* Сначала просматриваются локальные области видимости функции-члена.

* Если шаг 1 не привел к успеху, то просматриваются объявления всех членов вложенного класса.

* Если имя еще не найдено, то просматриваются объявления всех членов объемлющего класса.

* Если и этого недостаточно, то просматриваются объявления, появляющиеся в области видимости пространства имен перед определением функции-члена.

Какое объявление относится к имени list в определении функции-члена check_status() в следующем фрагменте кода:

class List {

public:

enum ListStatus { Good, Empty, Corrupted };

// ...

private:

class ListItem {

public:

void check_status();

ListStatus status; // правильно

//...

};

ListItem *list;

};

int list = 0;

void List::ListItem::check_status()

{

int value = list; // какой list?

}

* Весьма вероятно, что при использовании list внутри check_status() программист имел в виду глобальный объект: и value, и глобальный объект list имеют тип int. Член List::list объявлен как указатель и не может быть присвоен value без явного приведения типа;

* ListItem не имеет прав доступа к закрытым членам объемлющего класса, в частности list;

* list – это нестатический член, и обращение к нему в функциях-членах ListItem должно производиться через объект, указатель или ссылку.

Однако, несмотря на все это, имя list, встречающееся в функции-члене check_status(), разрешается в пользу члена list класса List. Напоминаем, что если имя не найдено в области видимости вложенного ListItem, то далее просматривается область видимости объемлющего класса, а не глобальная. Член list в List скрывает глобальный объект. А так как использование указателя list в check_status() недопустимо, то выводится сообщение об ошибке.

Права доступа и совместимость типов проверяются только после того, как имя разрешено. Если при этом обнаруживается ошибка, то выдается сообщение о ней и дальнейший поиск объявления, которое было бы лучше согласовано с именем, уже не производится. Для доступа к глобальному объекту list следует использовать оператор разрешения области видимости:

void List::ListItem::check_status()

{

int value = ::list; // правильно

}

Если бы функция-член check_status() была определена как встроенная в теле класса ListItem, то последнее объявление привело бы к выдаче сообщения об ошибке из-за того, что имя list не объявлено в глобальной области видимости:

class List {

public:

// ...

private:

class ListItem {

public:

// ошибка: нет видимого объявления для ::list

void check_status() { int value = ::lis; }

//...

};

ListItem *list;

// ...

};

int list = 0;

Глобальный объект list объявлен после определения класса List. Во встроенной функции-члене, определенной внутри тела класса, рассматриваются только те глобальные объявления, которые были видны перед определением объемлющего класса. Если же определение check_status() следует за определением List, то рассматриваются глобальные объявления, расположенные перед ним, поэтому будет найдено глобальное определение объекта list.

Упражнение 13.21

В главе 11 был приведен пример программы, использующей класс iStack. Измените его, объявив классы исключений pushOnFull и popOnEmpty открытыми вложенными в iStack. Модифицируйте соответствующим образом определение класса iStack и его функций-членов, а также определение main().

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

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

Из книги Программирование автора Козлова Ирина Сергеевна

13. Область видимости Областью при видимости называется часть текста программы, в которой может быть использован определенный объект. Объект является видимым в блоке или в исходном файле, когда в данном блоке или файле определены имя и тип объекта. Объект может быть


R.10.4 Сводка правил области видимости

Из книги Справочное руководство по C++ автора Страустрап Бьярн

R.10.4 Сводка правил области видимости Теперь можно свести воедино правила областей видимости для программы на C++. Эти правила одинаково применимы для всех имен (включая имя-typedef (§R.7.1.3) и имя-класса (§R.9.1)) и в любом контексте, для которого они допустимы по синтаксису языка.


Разрешение конфликтов имен

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

Разрешение конфликтов имен Явная реализаций интерфейса может оказаться очень полезной тогда, когда реализуются несколько интерфейсов, содержащих идентичные члены, Предположим. например, что вы создали класс, реализующий следующие новые типы интерфейса.// Три


10. Не прячьте ваши денежки, или Расчет дохода от вложенного капитала

Из книги Этюды для программистов [неполностью, главы 1–24] автора Уэзерелл Чарлз

10. Не прячьте ваши денежки, или Расчет дохода от вложенного капитала Самым разным людям — финансистам, биржевым дельцам, банкирам и даже обыкновенным труженикам, вроде казначея пенсионного фонда Тимстеров[13], — хотелось бы знать, какой доход принесут им вложенные


Обзор области видимости

Из книги VBA для чайников автора Каммингс Стив

Обзор области видимости Каждая VBA-процедура имеет свою вполне определенную область видимости. Область видимости определяет, из какой части программы вы можете вызвать эту процедуру, а из какой - нет. Можно сказать, что область видимости отвечает за то, какая часть


Задание области видимости процедуры

Из книги C++. Сборник рецептов автора Диггинс Кристофер

Задание области видимости процедуры Чтобы задать область видимости процедуры, нужно в начале объявления процедуры просто напечатать ключевое слово Public или Private. Взгляните на следующие примеры:Public Sub IKr.eadYouO...( операторы процедуры)End SubPrivate Function IKneedYou().. . (операторы


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

Из книги C++ для начинающих автора Липпман Стенли

Задание области видимости переменной Область видимости переменной (т.е. та часть программы, в рамках которой данная переменная доступна) зависит от следующих двух взаимосвязанных факторов:* места объявления переменной (либо внутри процедуры, либо в разделе объявлений


2.4. Предотвращение конфликта имен с помощью пространств имен

Из книги автора

2.4. Предотвращение конфликта имен с помощью пространств имен ПроблемаВ несвязанных между собой модулях обнаружены конфликтующие имена или требуется заранее избежать возможности таких конфликтов, создав логические группы кода.РешениеДля структурирования кода


8.5.2. Оператор разрешения области видимости

Из книги автора

8.5.2. Оператор разрешения области видимости Имя члена пользовательского пространства дополняется поставленным спереди именем этого пространства и оператором разрешения области видимости (::). Использование неквалифицированного члена, например matrix, является ошибкой.


10.9. Разрешение имен в определениях шаблонов А

Из книги автора

10.9. Разрешение имен в определениях шаблонов А Внутри определения шаблона смысл некоторых конструкций может различаться в зависимости от конкретизации, тогда как смысл других всегда остается неизменным. Главную роль играет наличие в конструкции формального параметра


13.9.1. Разрешение имен в области видимости класса

Из книги автора

13.9.1. Разрешение имен в области видимости класса Конечно, имена, используемые в области видимости класса, не обязаны быть именами членов класса. В процессе разрешения в этой области ведется поиск имен, объявленных и в других областях. Если имя, употребленное в области


16.11. Разрешение имен в шаблонах классов A

Из книги автора

16.11. Разрешение имен в шаблонах классов A При обсуждении разрешения имен в шаблонах функций (см. раздел 10.9) мы уже говорили о том, что этот процесс выполняется в два шага. Так же разрешаются имена и в определениях шаблонов классов и их членов. Каждый шаг относится к разным