Nested classes
Una declaración de una class/struct o union puede aparecer dentro de otra clase. Dicha declaración define una clase anidada .
Explicación
El nombre de la clase anidada existe en el ámbito de la clase envolvente, y la búsqueda de nombres desde una función miembro de una clase anidada visita el ámbito de la clase envolvente después de examinar el ámbito de la clase anidada. Como cualquier miembro de su clase envolvente, la clase anidada tiene acceso a todos los nombres (private, protected, etc) a los que la clase envolvente tiene acceso, pero por lo demás es independiente y no tiene acceso especial al
this
pointer
de la clase envolvente. Las declaraciones en una clase anidada pueden usar cualquier miembro de la clase envolvente, siguiendo las
reglas de uso habituales
para los miembros no estáticos.
int x, y; // variables globales class enclose // clase envolvente { // nota: miembros privados int x; static int s; public: struct inner // clase anidada { void f(int i) { x = i; // Error: no se puede escribir en enclose::x no estático sin instancia int a = sizeof x; // Error hasta C++11, // OK en C++11: el operando de sizeof no se evalúa, // este uso de enclose::x no estático está permitido. s = i; // OK: se puede asignar al enclose::s estático ::x = i; // OK: se puede asignar a la variable global x y = i; // OK: se puede asignar a la variable global y } void g(enclose* p, int i) { p->x = i; // OK: asignar a enclose::x } }; };
Friend Las funciones amigas definidas dentro de una clase anidada no tienen acceso especial a los miembros de la clase envolvente, incluso si la búsqueda desde el cuerpo de una función miembro que está definida dentro de una clase anidada puede encontrar los miembros privados de la clase envolvente.
Las definiciones fuera de la clase de los miembros de una clase anidada aparecen en el espacio de nombres de la clase contenedora:
struct enclose { struct inner { static int x; void f(int i); }; }; int enclose::inner::x = 1; // definición void enclose::inner::f(int i) {} // definición
`, `` y términos específicos de C++.
Las clases anidadas pueden declararse por adelantado y definirse posteriormente, ya sea dentro del mismo cuerpo de la clase envolvente, o fuera de él:
class enclose { class nested1; // declaración anticipada class nested2; // declaración anticipada class nested1 {}; // definición de clase anidada }; class enclose::nested2 {}; // definición de clase anidada
Las declaraciones de clases anidadas obedecen los especificadores de acceso de miembros , una clase miembro privada no puede ser nombrada fuera del alcance de la clase envolvente, aunque los objetos de esa clase pueden ser manipulados:
class enclose { struct nested // miembro privado { void g() {} }; public: static nested f() { return nested{}; } }; int main() { //enclose::nested n1 = enclose::f(); // error: 'nested' es privado enclose::f().g(); // OK: no nombra 'nested' auto n2 = enclose::f(); // OK: no nombra 'nested' n2.g(); }
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 45 | C++98 |
los miembros de una clase anidada no pueden
acceder a la clase envolvente y sus amigos |
tienen los mismos derechos de acceso que
otros miembros de la clase envolvente (también resuelve los problemas CWG #8 y #10) |
Referencias
- Estándar C++23 (ISO/IEC 14882:2024):
-
- 11.4.12 Declaraciones de clases anidadas [class.nest]
- Estándar C++20 (ISO/IEC 14882:2020):
-
- 11.4.10 Declaraciones de clases anidadas [class.nest]
- Estándar C++17 (ISO/IEC 14882:2017):
-
- 12.2.5 Declaraciones de clases anidadas [class.nest]
- Estándar C++14 (ISO/IEC 14882:2014):
-
- 9.7 Declaraciones de clases anidadas [class.nest]
- Estándar C++11 (ISO/IEC 14882:2011):
-
- 9.7 Declaraciones de clases anidadas [class.nest]
- Estándar C++98 (ISO/IEC 14882:1998):
-
- 9.7 Declaraciones de clases anidadas [class.nest]