2011-05-14 13 views
8

Estoy teniendo problemas para acceder a un miembro privado de una clase de un amigo.¿Por qué no puedo cambiar a un miembro privado de una clase de una clase de amigo en un espacio de nombres diferente?

La clase que contiene el miembro privado que quiero cambiar y la clase donde se realiza el cambio se encuentran en diferentes espacios de nombres.

La clase de amigo se define después de la clase que contiene los datos, por lo que he intentado reenviar declarar la clase de amigo fuera del espacio de nombres.

g ++ dice que no puedo modificar el miembro porque es privado, el estudio visual parece pensar que está bien.

¿Estoy haciendo algo extraño no estándar aquí? ¿Por qué no puedo cambiar el miembro? Aquí hay un fragmento simplificado que representa mi problema:

struct S; 

namespace N 
{ 
    class A 
    { 
     int m; 
    public: 
     A():m(5){}; 
     friend struct S; 
    }; 

} 

using namespace N; 

struct S 
{ 
    A& a; 
    S(A& a):a(a) {} 
    void changeA(){ a.m = 9; } 
}; 

int main() 
{ 
    A a; 
    S s(a); 
    s.changeA(); 
} 

Respuesta

9
friend struct ::S; 

lo que está haciendo en realidad con

friend struct S; 

está declarando como amigo de la clase N :: S (que se define en ninguna parte).

Editar: Para respaldar mi idea de que el comportamiento de gcc es correcto y VC++ tiene un error.

7.3.1.2/3

Si una declaración friend en una clase que no es local declara por primera vez una clase o función de la clase de amigo o de la función es un miembro del espacio de nombres que encierra más interna . [...] Cuando se busca una declaración previa de una clase o función introducida por una declaración de amigo, no se consideran los ámbitos fuera del alcance del espacio de nombres más interior .

+0

pregunto por qué lo toma Visual Studio entonces –

+0

@Jacobo: Porque es válido. Siempre puede 'amigo' una estructura o clase, incluso si aún no se ha declarado. – aschepler

+0

Los miembros de @Jacob friend no necesitan existir realmente. Esto es realmente útil cuando su miembro amigo es una plantilla, pero nadie usa la plantilla. Además de lo que dijo aschepler. –

4

Intente escribir friend struct ::S;.

Por el momento, se supone que no existe N::S. Esta solución especifica el espacio de nombres global, algo así como la forma en que el / líder en una ruta Linux especifica la raíz del sistema de archivos.

5

Porque friend struct S; declara la clase N::S pero necesita la clase ::S.

Cuestiones relacionadas