2008-12-24 11 views
17

¿Alguien sabe por qué los typedefs de los nombres de clase no funcionan como nombres de clase para la declaración de amigo?¿Por qué no puedo declarar a un amigo a través de un typedef?

class A 
{ 
public: 
}; 

class B : public A 
{ 
public: 
    typedef A SUPERCLASS; 
}; 

typedef A X; 

class C 
{ 
public: 
    friend class A;    // OK 
    friend class X;    // fails 
    friend class B::SUPERCLASS; // fails 
}; 

Respuesta

9

No puede, actualmente. Todavía no sé el motivo (simplemente buscándolo, porque me parece interesante). Actualización: puede encontrar el motivo en la primera propuesta para admitir typedef-names como amigos: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1520.pdf. La razón es que el estándar solo admitía especificadores de tipo elaborado. Es fácil permitir solo eso, y decir si la entidad declarada como amigo aún no está declarada, se convertirá en un miembro del espacio de nombres circundante. Pero esto significa que si usted desea utilizar un parámetro de plantilla, que tendría que hacer (se requiere una clase a continuación, por ejemplo)

friend class T; 

pero que trajo problemas adicionales, y fue descubierto no vale la pena la ganancia. Ahora, el documento propone permitir que se especifiquen especificadores de tipo adicionales (para que luego esto permita el uso de parámetros de plantilla y nombresdedef tipo).

La próxima versión de C++ (debido a 2010) podrá hacerlo.

Consulte esta propuesta actualizada al estándar: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf. No permitirá solo los nombres typedef, sino también los parámetros de plantilla que se utilizarán como el tipo declarado como amigo.

0

yo sepa, en C++ typedef no crea una definición de pleno derecho cuando se utiliza en conjunción con las clases. En otras palabras, no es como una macro.

Entre las restricciones se encuentra que el sinónimo no puede aparecer después de un prefijo de clase o estructura, o puede usarse como un destructor o nombre de constructor. Tampoco puedes subclasificar el sinónimo. Apostaría que eso también significa que no puedes ser amigo.

1

me trataron en el VC++ 8.0 el código:

... 
class C 
{ 
public: 
    friend class A;  
    friend X;    
    friend B::SUPERCLASS; 
}; 
... 

se compila sin errores.

No sé si es MS específico o no.

0

Un typedef define un tipo. Los amigos decls declaran clases o funciones de amigo (sustancialmente ámbitos), que luego tienen "acceso" al área no pública de la clase declarante ...

Primitivos, i.E. un float o un int * no definen un ámbito con código, etc., , de todos modos, no "usan" la clase.

No olvide, también puede "empaquetar" convenciones de llamadas, atributos de alineación y otras cosas específicas del compilador en un typedef, es decir, TYPES de vectores múltiples implementados por la misma clase pero con diferentes atributos attribs. => Un tipo no es una clase, sino viceversa.

En mi humilde opinión, declarar un amigo typedef puede ser útil, pero cuando se puede establecer "friend typedefs" desde cualquier lugar como amigo, las amistades pueden ser extremadamente incomprensibles y propensas a errores, especialmente cuando las plantillas se usan excesivamente.

Invalidar un typedef individual puede arruinar todo el proyecto debido a dependencias generalizadas. Los amigos de plantillas y los de tipo 0x typedefs son útiles, pero no relajen las reglas de una declaración de amigo.

No conozco ninguna propuesta relativa a friend typedefs.

0
class MyClass 
{ 
    friend class ClassFromTypedef; 

    // ... 
}; 

no funciona mientras

template<class T> 
struct get_type{ typedef T type;}; 

class MyClass 
{ 
    friend class get_type<ClassFromTypedef>::type; 

    // ... 
}; 

parece funcionar para mí en gcc-4.6.0 con el --std = C++ 0x opción (no sé si se trata de significativo). no funciona ... (Lo siento, estaba alucinando)

+2

Dado que su respuesta no proporciona ninguna información útil, ¿considera usted eliminarla? –

Cuestiones relacionadas