2010-09-06 13 views
5

Con este código (sólo una clase de prueba):Cómo tener un Struct con la plantilla con una clase

typedef unsigned short UInt16; 

template<class T> 
class CClass 
{ 
public: 
    SValue* getNewSValue(void); 
private: 
    typedef struct { 
     T *mValue; 
     T *next; 
     T *previous; 
     UInt16 index; 
    } SValue; 
}; 

template<typename T> 
SValue* CClass<T>::getNewSValue(void) 
{ 
    return new SValue; 
} 

tengo los siguientes errores:

error C2143: syntax error : missing ';' before '*'

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

¿Es posible utilizar una ¿Construir dentro de una clase? Si declaro la estructura fuera de la clase, la plantilla no ve la plantilla T.

+2

+1: pregunta con un formato agradable – Chubsdad

Respuesta

0

Parece que su struct no está definido cuando declara el tipo de devolución de getNewSValue.

Con que no tienen ese error:

template<class T> 
class CClass 
{ 
public: 
    SValue* getNewSValue(void); 
private: 
    typedef struct { 
     T *mValue; 
     T *next; 
     T *previous; 
     UInt16 index; 
    } SValue; 
}; 

template<typename T> 
SValue* CClass<T>::getNewSValue(void) 
{ 
    return new SValue; 
} 

Y también hay que calificar el tipo SValue de retorno, ya que se anida en CClass cuando lo utiliza para definir getNewSValue.

0

Declarar SValue antes getNewSValue():

template<class T> 
class CClass 
{ 
private: 
    typedef struct { 
     T *mValue; 
     T *next; 
     T *previous; 
     UInt16 index; 
    } SValue; 
public: 
    SValue* getNewSValue(void); 
}; 

Además, asegúrese de UInt16 se define.

3

$ 9,2/2- La clave es el siguiente cita de la C++ Standard03

`Una clase se considera un tipo definido completamente a objetos (3,9) (o de tipo completo) en el cierre} de la clase-especificador . Dentro de la especificación de miembro de clase, la clase se considera completa dentro de cuerpos de función, argumentos predeterminados e inicializadores de ctores de constructor (incluidos dichos elementos en clases anidadas). De lo contrario, se considera incompleto dentro de su propia especificación de miembro de clase.

No sabe lo que es UINT16, pero el siguiente debería funcionar

template<class T> 
class CClass 
{ 
private: 
    typedef struct { 
     T *mValue; 
     T *next; 
     T *previous; 
     short int index;      // Replacing with int for illustration only 
    } SValue; 
public: 
    SValue* getNewSValue(void); 
private: 
}; 

Datos 3: El *** llegaron allí tratando de hacer el cambio BOLD (que debería haber eliminado todos modos)

template<class T> typename CClass<T>::SValue* CClass<T>::getNewSValue(void) 
{ 
    return new SValue; 
} 

int main(){ 
    CClass<int> s; 
    s.getNewSValue(); 
} 
+0

¿Cuál es el propósito de la 'typename' keywork en la definición de' getNewSValue'? ¿Eso es porque SValue no tiene nombre y tenemos que referirnos a él usando el nombre 'typedef'? –

+0

@Cedric si omitiéramos 'typename', sería analizado como la definición de un miembro llamado' SValue' de la clase 'CClass ', para el cual no se especificó ningún tipo: 'tempate Clase :: SValue;'. Los tokens siguientes serían basura y el compilador los rechazaría como errores de sintaxis. Todo esto se debe a que el compilador asume por defecto no-tipos si no puede buscar un nombre en el tiempo de análisis (es decir, no sabe qué es 'T' todavía, por lo que no puede buscar' SValue'). Si pones 'typename',' SValue' se considera correctamente como un nombre de tipo para el miembro 'getNewSValue'. –

+0

El código que coloca genera el siguiente error: "error C2244: 'CClass :: getNewSValue': no ​​se puede hacer coincidir la definición de la función con una declaración existente" – okami

0

¿Qué tal si lo intentas? funcionó en VS2008

template<class T> 
class CClass 
{ 
private: 
    typedef struct { 
     T *mValue; 
     T *next; 
     T *previous; 
     __int16 index; 
    } SValue; 

public: 
    SValue* getNewSValue(void) 
    { 
     return new SValue; 
    } 
}; 
0

El SValue-Type está dentro del espacio de nombres CClass. Necesita calificar completamente el nombre de tipo fuera de la clase.

template<typename T> 
CClass<T>::SValue* CClass<T>::getNewSValue(void) 

Además, debe hacer público SValue, si se devuelve mediante un método público.

0

Para el registro, ninguno de estos compilará (en GCC 4.2 al menos) tan pronto como se llame al getNewSValue(). Dado que es un método público que devuelve un puntero a un tipo privado, obtendrá un error de compilación que indica que SValue is private.

Para que esto funcione, ya sea que usted necesita para hacer pública SValue, o cambiar el tipo del valor de retorno de getNewSValue() a algo así como void*, ya que parece que está tratando de hacer SValue un tipo opaco.

1

Dado que la definición de la función miembro está en el ámbito global, necesita calificar su tipo de devolución con CClass:: para referirse al nombre dentro del alcance de la clase. Además, la palabra clave typename es necesaria cuando se hace referencia a nombres de tipos anidados en plantillas.

template<typename T> 
typename CClass<T>::SValue* CClass<T>::getNewSValue(void) 

Además, la estructura anidada no tiene nombre. Tenga en cuenta que en C++, las clases y las estructuras tienen nombres propios, y un nombre typedef no es un nombre de clase. Estarás mucho mejor evitando el typedef.

struct SValue { 
    T *mValue; 
    T *next; 
    T *previous; 
    UInt16 index; 
}; 
+0

Esto es muy detallado :-), pero Potatos tu código genera el siguiente error, en la línea: typename CClass :: SValue * CClass :: getNewSValue (void) ERROR ---> "error C2899: typename no se puede usar fuera de una declaración de plantilla" – okami

+0

@okami: mantener la parte 'template '. Para una sintaxis menos detallada, defina la función dentro del alcance 'clase {}'. Entonces 'typename' y calificación (en tipos de clase local) no son necesarios. – Potatoswatter

Cuestiones relacionadas