2010-08-21 44 views
16

Este código se compila en msvc/g ++:clases anidadas: El acceso a miembro protegido de la clase envolvente de una clase anidada protegida

class A{ 
protected: 
    int i; 
    class B{ 
    public: 
     A* a; 
     B(A* a_) 
     :a(a_){ 
     } 
     void doSomething(){ 
      if (a) 
       a->i = 0;//<---- this part 
     }  
    }; 
public: 
    A() 
    :i(0){ 
    } 
}; 

Como se puede ver, B tiene acceso a la sección "protegido" de la clase que lo contiene, aunque no está declarado como amigo.

¿Es este un comportamiento estándar (conforme a las normas)?

A veces uso esta característica, pero no recuerdo una regla que diga que la clase protegida anidada debería tener automáticamente acceso a todos los datos protegidos de la clase adjunta.

+0

Dupe question. Sin embargo, no voy a buscar el original ahora. :) –

Respuesta

13

En el estándar C++ 03, 11.8p1 dice:

Los miembros de una clase anidada no tienen acceso especial a los miembros de una clase envolvente.

Sin embargo, la resolución de defect report 45 (al estándar) establece lo contrario, y por lo tanto define el comportamiento que se ve:

Una clase anidada es un miembro y como tal tiene el mismo acceso derechos como cualquier otro miembro.

En C++ 0x el texto de 11.8 ha cambiado para reflejar este hecho, por lo que este es un comportamiento válido tanto para C++ 03 y C++ 0x compiladores conformes.

Véase también this thread de los foros cprogramming.com.

+2

+1 Buena respuesta. Sin embargo, si busca en Google esto, hay alguna documentación del compilador de IBM XL que solo menciona la primera parte que ha indicado e implica que el código del OP no se compilará. Entonces, lo que se puede hacer en la actualidad, hasta que C++ 0x se implemente ampliamente, sería declarar a la clase anidada como un amigo dentro de la clase adjunta. – Praetorian

+0

Buen descubrimiento. Un enlace sería bueno por el bien de la completitud. :) –

+0

Estaba siendo perezoso antes :-), aquí está el enlace. http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/language_ref/cplr061.html – Praetorian

0

Consultar $ 9.7/1.

"La clase anidada está dentro del alcance de su clase adjunta. Excepto al utilizar punteros, referencias y nombres de objetos explícitos, las declaraciones en una clase anidada solo pueden usar nombres de tipo , miembros estáticos y enumeradores de la clase adjunta "

5

no tengo una copia de C++ 03 conveniente, pero a partir de un proyecto (n3090) de C++ 0x:

11.8 clases anidadas

Un anidada La clase es miembro y, como tal, tiene los mismos derechos de acceso que cualquier otro miembro. Los miembros de una clase adjunta no tienen acceso especial a los miembros de una clase anidada ; las reglas de acceso usuales (Cláusula 11) deben ser obedecidas.

[Ejemplo:

class E { 
    int x; 
    class B { }; 
    class I { 
     B b; // OK: E::I can access E::B 
     int y; 
     void f(E* p, int i) { 
      p->x = i; // OK: E::I can access E::x 
     } 
    }; 
    int g(I* p) { 
     return p->y; // error: I::y is private 
    } 
}; 

Así que al menos en el próximo estándar, clases cerrados pueden tener acceso a los miembros de la clase externa como cualquier miembro de la función normal haría.

Actualización: Esto no está permitido en el estándar actual. Pero se envió un informe de defectos (DR 45) para solucionarlo.(edición de sigterm tomó éste hacia fuera Por favor, tenga cuidado..)

Actualización # 2: He intentado con VS2010, g ++ (4.0.1 Apple) con -Wall -ansi -pedantic -std=c++98 y Comeau (4.3.10.1) en estricta C + Modo +03 con extensiones C++ 0x deshabilitadas: todas ellas parecen aceptar el acceso a los miembros de la clase externa private en los miembros de la clase interna.

0

¿Es este un comportamiento estándar (conforme a las normas)?

No.

Según C++ - 2003

Section 11.8.1

clases anidadas

Los miembros de una clase anidada no tienen acceso especial a los miembros de una clase envolvente, ni a las clases o funciones que han otorgado amistad a una clase que los encierra; las reglas de acceso usuales (cláusula 11) deben ser obedecidas. Los miembros de una clase adjunta no tienen acceso especial a los miembros de una clase anidada; las reglas de acceso usuales (cláusula 11) deben ser obedecidas.

[Example: 
class E { 

    int x; 
    class B { }; 
    class I { 

     B b; //error: E::B is private 
     int y; 
     void f(E* p, int i) 
     { 
      p->x = i;   //error: E::x is private 
     } 
    }; 
    int g(I* p) 
    { 
      return p->y; //error: I::y is private 
    } 
}; 
—end example] 

Pero hay una ligera modificación a esa sección en la que dice ISO/IEC N 3092

Una clase anidada es miembro y como tal tiene los mismos derechos de acceso que cualquier otro miembro de. Los miembros de una clase adjunta no tienen acceso especial a los miembros de una clase anidada; las reglas de acceso usuales (Cláusula 11) deben ser obedecidas.

Cuestiones relacionadas