Пространства имён
Варианты
Действия

Вложенные классы

Материал из cppreference.com
< cpp‎ | language
 
 
 
 

Объявление класса/структуры или объединения может содержать внутри другой класс. Это и будет Вложенный класс.

[править]Объяснение

Имя вложенного класса существует в области видимости окружающего класса и поиск имён из метода вложенного класса посетит область видимости окружающего класса, если в своём ничего не найдёт. Как и любой элемент окружающего класса, вложенный класс имеет доступ ко всем именам (приватным, защищённым и так далее) к которым окружающий класс имеет доступ, но так или иначе является независимым и не имеет специального доступа к указателю this окружающего класса.

Объявления во вложенном классе могут использовать только имена типов, статические элементы и перечислители из окружающего класса. (до C++11)

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

(начиная с C++11)
int x,y;// глобальные переменныеclass enclose // окружающий класс{// заметьте: закрытые элементыint x;staticint s;public:struct inner // вложенный класс{void f(int i){ x = i;// Ошибка: не возможно записать в нестатический// enclose::x без экземпляра int a = sizeof x;// Ошибка до С++11,// OK в С++11: операнд не оценивается// такое использование нестатического// enclose::x допустимо. s = i;// OK: могу присвоить статическому enclose::s::x= i;// OK: могу присвоить глобальному x y = i;// OK: могу присвоить глобальному y}   void g(enclose* p, int i){ p->x = i;// OK: присваивание enclose::x}};};

Дружественные функции, определённые во вложенном классе не имеют специального доступа к элементам окружающего класса даже если поиск имён из тела методов, объявленных внутри вложенного класса, может найти закрытые элементы окружающего класа.

Внеклассовые определения элементов вложенного класса содержатся в пространстве имён внешнего класса:

struct enclose {struct inner {staticint x;void f(int i);};};   int enclose::inner::x=1;// определениеvoid enclose::inner::f(int i){}// определение

Вложенные классы могут быть заранее объявлены и позднее определены, как внутри тела внешнего класса, так и снаружи:

class enclose {class nested1;// предварительное объявлениеclass nested2;// предварительное объявлениеclass nested1 {};// определение вложенного класса};   class enclose::nested2{};// определение вложенного класса

Определения вложенного класса подчиняются спецификаторам доступа, закрытые элементы не могут быть именованы снаружи области видимости внешнего класса, несмотря на то что объекты этого класса могут быть использованы:

class enclose {struct nested // закрытый элемент{void g(){}};public:static nested f(){return nested{};}};   int main(){//enclose::nested n1 = enclose::f(); // ошибка: 'nested' является закрытым   enclose::f().g();// OK: не именует 'nested'auto n2 = enclose::f();// OK: не именует 'nested' n2.g();}

[править]Отчёты об ошибках

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
CWG 45 C++98 элементы вложенных классов не могли
иметь доступа к окружающему классу и его друзьям
имеют те-же права доступа, как и
другие элементы окружающего класса
(также решило CWG проблемы №8 и №10)

[править]Ссылки

  • C++20 стандарт (ISO/IEC 14882:2020):
  • 11.4.10 Объявления вложенных классов [class.nest]
  • C++17 стандарт (ISO/IEC 14882:2017):
  • 12.2.5 Объявления вложенных классов [class.nest]
  • C++14 стандарт (ISO/IEC 14882:2014):
  • 9.7 Объявления вложенных классов [class.nest]
  • C++11 стандарт (ISO/IEC 14882:2011):
  • 9.7 Объявления вложенных классов [class.nest]
  • C++98 стандарт (ISO/IEC 14882:1998):
  • 9.7 Объявления вложенных классов [class.nest]
close