una resueltos programacion polimorfismo orientada objetos miembros metodos herencia ejercicios ejemplos constructores codigo clases clase c++ namespaces friend forward-declaration

c++ - resueltos - miembros de una clase en programacion orientada a objetos



¿Por qué una clase de amigo de C++ necesita una declaración directa solo en otros espacios de nombres? (3)

Norma C++ ISO/IEC 14882:2003(E)

7.3.1.2 Definiciones de miembro de espacio de nombres

Párrafo 3

Cada nombre declarado por primera vez en un espacio de nombres es un miembro de ese espacio de nombres . Si una declaración de amigo en una clase no local declara primero una clase o función (esto implica que el nombre de la clase o función no está calificado), la clase o función amiga es un miembro del espacio de nombres más interno que lo rodea.

// Assume f and g have not yet been defined. void h(int); template <class T> void f2(T); namespace A { class X { friend void f(X); // A::f(X) is a friend class Y { friend void g(); // A::g is a friend friend void h(int); // A::h is a friend // ::h not considered friend void f2<>(int); // ::f2<>(int) is a friend }; }; // A::f, A::g and A::h are not visible here X x; void g() { f(x); } // definition of A::g void f(X) { /* ... */} // definition of A::f void h(int) { /* ... */ } // definition of A::h // A::f, A::g and A::h are visible here and known to be friends }

Tu friend class BF; es una declaración de A::BF en el espacio de nombres A en lugar del espacio de nombres global. Necesita la declaración previa global para evitar esta nueva declaración.

Supongamos que tengo una clase F que debería ser amiga de las clases G (en el espacio de nombres global) y C (en el espacio de nombres A ).

  • ser amigo de A::C , F debe ser declarado adelante.
  • para ser amigo de G , no es necesaria ninguna declaración directa de F
  • asimismo, una clase A::BF puede ser amiga de A::C sin declaración directa

El siguiente código ilustra esto y compila con GCC 4.5, VC ++ 10 y al menos con otro compilador.

class G { friend class F; int g; }; // without this forward declaration, F can''t be friend to A::C class F; namespace A { class C { friend class ::F; friend class BF; int c; }; class BF { public: BF() { c.c = 2; } private: C c; }; } // namespace A class F { public: F() { g.g = 3; c.c = 2; } private: G g; A::C c; }; int main() { F f; }

Para mí esto parece inconsistente. ¿Hay alguna razón para esto o solo es una decisión de diseño del estándar?


Porque no tendría sentido poder declarar algo en el espacio de nombres global si estás dentro de un bloque de namespace {} . La razón friend class BF; funciona es que actúa como una declaración directa implícita.


Tomemos en cuenta estas 3 líneas de código de su muestra:

1. friend class F; // it creates "friend declaration", (that''s not the same as ordinary forward declaration 2. class F; // without this forward declaration, F can''t be friend to A::C <-- this is ordinary forward declaration 3. friend class ::F; // this is qualified lookup (because of ::), so it needs previous declaration, which you provide in line 2.

El estándar de C ++ en el párrafo 7.3.1.2, punto 3 (definiciones de miembro de espacio de nombres) dice:

La declaración de amigo no hace que el nombre sea visible para búsqueda no calificada (3.4.1) o búsqueda calificada (3.4.3). [Nota: El nombre del amigo será visible en su espacio de nombres si se proporciona una declaración coincidente en el ámbito del espacio de nombres (ya sea antes o después de la definición de clase que otorga la amistad). -finalizar nota]

Y la línea 2 sigue exactamente lo que requiere el estándar.

Toda la confusión se debe a que la "declaración de amigo" es débil , debe proporcionar una declaración directa sólida para un uso posterior.