|
Программирование >> Инициализация объектов класса, структура
enum ListStatus { Good, Empty, Corrupted }; class List { public: ... private: class ListItem { public: Смотрим в: 1) List::ListItem 2) List 3) глобальной области видимости ListStatus status; относится к глобальному перечислению ... ... Например: Сначала компилятор ищет объявление ListStatus в области видимости класса ListItemi. Поскольку его там нет, поиск продолжается в области видимости List, а затем в глобальной. При этом во всех трех областях просматриваются только объявления, предшествующие использованию ListStatus. В конце концов находится глобальное объявление перечисления ListStatus - оно и будет типом, использованным в объявлении status. Если вложенный класс ListItem определен в глобальной области видимости, вне тела объемлющего класса List, то все члены List уже были объявлены: поскольку они доступны непосредственно в той области видимости, в которой определено само перечисление. Почему? Потому что с ним, в отличие от класса, не связана отдельная область. 13.10.1. Разрешение имен в области видимости вложенного класса Посмотрим, как разрешаются имена в определениях вложенного класса и его членов. Имя, встречающееся в определении вложенного класса (кроме тех, которые употребляются во встроенных функциях-членах и аргументах по умолчанию) разрешается следующим образом: 1. Просматриваются члены вложенного класса, расположенные перед употреблением имени. 2. Если шаг 1 не привел к успеху, то просматриваются объявления членов объемлющего класса, расположенные перед употреблением имени. 3. Если и этого недостаточно, то просматриваются объявления, расположенные в области видимости пространства имен перед определением вложенного класса. 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. Сначала просматриваются локальные области видимости функции-члена. 2. Если шаг 1 не привел к успеху, то просматриваются объявления всех членов вложенного класса. 3. Если имя еще не найдено, то просматриваются объявления всех членов объемлющего класса. 4. Если и этого недостаточно, то просматриваются объявления, появляющиеся в области видимости пространства имен перед определением функции-члена. Какое объявление относится к имени 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 следует использовать оператор oid List::ListItem::check status() int value = ::list; правильно разрешения области видимости: Если бы функция-член check status() была определена как встроенная в теле класса ListItem, то последнее объявление привело бы к выдаче сообщения об ошибке из-за того, что имя list не объявлено в глобальной области видимости:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |