friendship and inheritance c++
¿Por qué no se puede remitir la clase de amigo declarado hacia adelante en la clase? (3)
Además de la respuesta de @dasblinkenlight, una nota en 3.3.2 Punto de declaración iluminado. 10 explícitamente dice que una declaración de amigo no introduce (y por lo tanto no "declara en adelante") un nombre de clase:
10 [Nota: las declaraciones de amigos se refieren a funciones o clases que son miembros del espacio de nombres adjunto más cercano, pero no introducen nuevos nombres en ese espacio de nombres ([namespace.memdef]).
El siguiente código no compila:
struct X {
friend class Y;
Y* ptr;
};
La cppreference describe la situación como
... Si el nombre de la clase que se usa en la declaración de amigo aún no se ha declarado, se declara en el momento.
Si el "punto" significa donde se declara la relación de amistad, entonces debería estar bien declarar el miembro Y* ptr
. ¿Por qué no se compila? ¿Dónde en la norma se prohíbe esto?
Este es un error en el sitio. Contradice la norma, que dice que la declaración de amistad no es un sustituto de una declaración hacia adelante:
7.3.1.2.3 Todo nombre declarado primero 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 por primera vez una clase, función, plantilla de clase o plantilla de función, el amigo es un miembro del espacio de nombres que lo contiene más interno. La declaración de amigo no hace que el nombre sea visible para la búsqueda no calificada o la búsqueda calificada.
La parte acerca de que el nombre no es visible para una búsqueda no calificada o calificada esencialmente significa que el nombre no se comporta como una declaración de reenvío.
Una forma de arreglar este código es simplemente agregar class
palabra clave de class
:
struct X {
friend class Y;
class Y* ptr;
};
Esto reenviará declarar class Y
en el ámbito global, si X
está en el ámbito global.