|
Программирование >> Инициализация объектов класса, структура
class Node { /* ... */ } class Tree { public: Node инкапсулирован внутри области видимости класса Tree В этой области Tree::Node скрает ::Node 1 ООО т\т ; г . правильно: разрешается в пользу вложенного класса: Tree::Node Node *tree; Tree::Node невидима в глобальной области видимости Node разрешается в пользу глобального объявления Node Node *pnode; class List public: public: Node инкапсулирован внутри области видимости класса List ой области List::Node скрывает ::Node В этой области List::Node скрывает ::Node class Node {...}; правильно: разрешается в пользу вложенного класса: List::Node Node *list; Не идеально, будем улучать class List { public: class ListItem { friend class List; объявление друга ListItem( int val=0 ); конструктор ListItem *next; указатель на собственный класс int value; ... private: ListItem *list; ListItem *at end; Для вложенного класса допустимы такие же вид1 членов, как и для невложенного: Закрытым называется член, который доступен только в определениях членов и друзей класса. У объемлющего класса нет нрава доступа к закрытым членам вложенного. Чтобы в определениях членов List можно было обращаться к закрытым членам ListItem, класс ListItem объявляет List как друга. Равно и вложенный класс не имеет никаких специальных прав доступа к закрытым членам объемлющего класса. Если бы нужно было разрешить ListItem доступ к закрытым членам класса List, то в объемлющем классе List следовало бы объявить вложенный класс как друга. В приведенном выше примере этого не сделано, поэтому ListItem не может обращаться к закрытым членам List. Объявление ListItem открытым членом класса List означает, что вложенный класс можно использовать как тип во всей программе, в том числе и за пределами определений членов и друзей класса. Например: Не идеально, будем улучать class List { public: ... private: class ListItem { ... ListItem *list; ListItem *at end; Поэтому лучше объявить вложенный класс ListItem закрытым членом List: Теперь тип ListItem доступен только из определений членов и друзей класса List, поэтому все члены класса ListItem можно сделать открытыми. При таком подходе объявление List как друга ListItem становится ненужным. Вот новое определение / / так луе class List { public: ... private: Теперь ListItem закрыт вложенн тип class ListItem { а его члены открыты public: ListItem( int val=0 ); ListItem *next; int value; ListItem *list; ListItem *at end; класса List: }; Конструктор ListItem не задан как встроенный внутри определения класса и, следовательно, должен быть определен вне него. Но где именно? Конструктор класса ListItem не является членом List и, значит, не может быть определен в теле последнего; его нужно определить в глобальной области видимости - той, которая содержит определение объемлющего класса. Когда функция-член вложенного класса не определяется как встроенная в теле, она должна быть определена вне самого внешнего из объемлющих классов. Вот как могло бы выглядеть определение конструктора ListItem. Однако показанный ниже синтаксис в глобальной области видимости некорректен: правильно: объявление в глобальной области видимости List::ListItem *headptr; Это дает более широкую область видимости, чем мы планировали. Вложенный ListItem поддерживает абстракцию класса List и не должен быть доступен во всей программе. class List { public: ... private: class ListItem { public: ListItem( int val=0 ); ... ошибка: ListItem вне области видимости ListItem:: ListItem( int val ) { ... } Проблема в том, что имя ListItem отсутствует в глобальной области видимости. При использовании его таким образом следует указывать, что ListItem - вложенный класс в области видимости List. Это делается путем квалификации имени ListItem именем имя вложенного класса квафировано именем объемщего List::ListItem::ListItem( int val value = val; next = 0; объемлющего класса. Следующая конструкция синтаксически правильна: Заметим, что квалифицировано только имя вложенного класса. Первый квалификатор List:: именует объемлющий класс и квалифицирует следующее за ним имя вложенного ListItem. Второе вхождение ListItem - это имя конструктора, а не вложенного класса. ошибка: конструктор называется ListItem, а не List::ListItem List::ListItem::List::ListItem( int val ) { value = val; next = 0; В данном определении имя члена некорректно: Если бы внутри ListItem был объявлен статический член, то его определение также следовало бы поместить в глобальную область видимости. Имя этого члена могло бы выглядеть так: int List::ListItem::static mem = 1024; Обратите внимание, что функции-члены и статические данные-члены не обязаны быть открытыми членами вложенного класса для того, чтобы их можно было определить вне его тела. Закрытые члены ListItem также определяются в глобальной области видимости. Вложенный класс разрешается определять вне тела объемлющего. Например, определение ListItem могло бы находиться и в глобальной области видимости:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |