Clases anidadas
Una declaración de una clase, estructura o unión (class/struct o union) puede aparecer dentro de otra clase. Tal declaración declara una clase anidada.
[editar] Explicación
El nombre de la clase anidada existe en el ámbito de la clase envolvente, y la búsqueda de nombres de 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. Al igual que cualquier miembro de su clase envolvente, la clase anidada tiene acceso a todos los nombres (privados, protegidos, etc.) a los que la clase envolvente tiene acceso, pero, aparte de eso, es independiente y no tiene acceso especial al puntero this de la clase envolvente.
Las declaraciones en una clase anidada solo pueden usar nombres de tipo, miembros estáticos y enumeradores de la clase envolvente. |
(hasta C++11) |
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. |
(desde C++11) |
int x,y; // globales class envolvente // clase envolvente { // nota: miembros privados int x; static int s; public: struct anidada // clase anidada { void f(int i) { x = i; // ERROR: no se puede escribir en envolvente::x no estática sin una instancia int a = sizeof x; // ERROR hasta C++11, // de acuerdo en C++11: operando de sizeof no está evaluado, // este uso de envolvente::x no estática se permite. s = i; // de acuerdo: se puede asignar a envolvente::s estática ::x = i; // de acuerdo: se puede asignar a x global y = i; // de acuerdo: se puede asignar a y global } void g(envolvente* p, int i) { p->x = i; // de acuerdo: asignar a envolvente::x } }; };
Las funciones amigas (friend) 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.
Definiciones fuera de la clase, de los miembros de una clase anidada, aparecen en el espacio de nombres de la clase envolvente:
struct envolvente { struct anidada { static int x; void f(int i); }; }; int envolvente::anidada::x = 1; // definición void envolvente::anidada::f(int i) {} // definición
Las clases anidadas pueden declararse por adelantado y luego definirse, ya sea dentro del mismo cuerpo de clase envolvente o fuera de él:
class envolvente { class anidada1; // declaración adelantada class anidada2; // declaración adelantada class anidada1 {}; // definición de clase anidada }; class envolvente::anidada2 { }; // definición de clase anidada
Las declaraciones de clase anidadas siguen las reglas de los especificadores de acceso a miembro. Un miembro de clase privado no se puede nombrar fuera del ámbito de la clase envolvente, aunque los objetos de esa clase se pueden manipular:
class envolvente { struct anidada // miembro privado { void g() {} }; public: static anidada f() { return anidada{}; } }; int main() { // envolvente::anidada n1 = envolvente::f(); // ERROR: 'anidada' es privada envolvente::f().g(); // de acuerdo: no nombra a 'anidada' auto n2 = envolvente::f(); // de acuerdo: no nombra a 'anidada' n2.g(); }
[editar] Informe de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento seg��n lo publicado | Comportamiento correcto |
---|---|---|---|
CWG 45 | C++98 | los miembros de una clase anidada no pueden acceder a la clase envolvente y sus amigas |
tienen las mismas normas de acceso que otros miembros de la clase envolvente (también resuelven los problemas del CWG n.º 8 y n.º 10) |
[editar] Referencias
- El estándar C++20 (ISO/IEC 14882:2020):
- 11.4.10 Nested class declarations [class.nest]
- El estándar C++17 (ISO/IEC 14882:2017):
- 12.2.5 Nested class declarations [class.nest]
- El estándar C++14 (ISO/IEC 14882:2014):
- 9.7 Nested class declarations [class.nest]
- El estándar C++11 (ISO/IEC 14882:2011):
- 9.7 Nested class declarations [class.nest]
- El estándar C++98 (ISO/IEC 14882:1998):
- 9.7 Nested class declarations [class.nest]