2011-05-28 6 views
7

¿Hay alguna forma de evitar esto:clases amigo recursivas

class B; 

class C { 
public: 
    C() { } 
private: 
    int i; 
    friend B::B(); 
}; 

class B { 
public: 
    B() { } 
private: 
    int i; 
    friend C::C(); 
}; 

produce un error:

prog.cpp:8: error: invalid use of incomplete type ‘struct B’ 
prog.cpp:1: error: forward declaration of ‘struct B’ 
+0

creo que el más cercano que puedes conseguir es 'B' amigo clase –

+1

¿Qué es exactamente lo que quiere hacer que se necesitaba el constructor de B y C para ser visible a los demás? –

+0

@Mike, eso es realmente un ejemplo sintético. La situación real es que, por razones complicadas para entrar, no puedo permitir que una dependencia en C fuerce una dependencia en la definición de B. – BCS

Respuesta

5

Usted simplemente no puede hacer esto. Elimina la dependencia circular.

+0

Oh. . . . Fud. – BCS

+0

Puede otorgar amistad a toda la clase recursivamente, pero no a miembros individuales. – Nemo

+0

@Nemo: De hecho. –

3

Según IBM's documentation (que me di cuenta de que no es normativo):

A class Y must be defined before any member of Y can be declared a friend of another class.

Así que creo que la respuesta es "no".

Por supuesto, puede utilizar

friend class B; 

... en lugar de friend B::B(), pero que otorga la amistad a todos los miembros de B. Y probablemente ya lo sabes.

2

Dado que eres muy selectivo con la amistad (acceso a funciones específicas de miembros dadas a clases específicas), el Attorney-Client Idiom puede ser lo que necesites. Sin embargo, no estoy seguro de lo bien que esto funcionará con los constructores.

1

Me doy cuenta de que esta es una idea realmente tonta, pero ¿no podría usted-teóricamente-lograr esto a través de la herencia, al hacer amigos de constructores de la clase padre? El código se compila, al menos, aunque sea cuestionable.

class A { 
public: 
    A() { } 
private: 
    int i; 
}; 

class D { 
public: 
    D() { } 
private: 
    int i; 
}; 

class B : public A { 
public: 
    B() { } 
private: 
    friend D::D(); 
}; 

class C : public D { 
public: 
    C() { } 
private: 
    friend A::A(); 
}; 
+3

Creo que la amistad no se puede heredar ... C no es amigo de B y B no es amigo de C aquí ... – vrince

+0

La amistad definitivamente no se hereda. – Nemo

+0

Es cierto. Pero si solo quisieras dar acceso a los constructores a variables privadas, esto haría que los datos privados en B y C sean accesibles para los constructores de las clases padre de B y C, que pueden ser llamados respectivamente por los constructores B y C, aunque B y C C no puede acceder directamente a los datos privados de los demás. –