2010-09-06 3 views
5

С помощью этого кода (только класса теста):Как иметь STRUCT с шаблоном с классом

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; 
} 

У меня есть следующие ошибки:

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

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

Можно ли использовать Структурировать внутри класса? Если я объявляю структуру из класса, шаблон не видит шаблон T.

+2

+1: красиво отформатирована вопрос – Chubsdad

ответ

0

Похоже, что ваш struct не определен, если вы заявляете тип возврата getNewSValue.

С, что вы не имеете эту ошибку:

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; 
} 

И вы также должны квалифицировать тип SValue возврата, потому что он вложен в CClass, когда вы используете его, чтобы определить getNewSValue.

0

Declare SValue перед тем getNewSValue():

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

Кроме того, убедитесь, что UInt16 определен.

3

$ 9,2/2- Ключ ниже цитата из С ++ Standard03

`Класс считается полностью определенный тип объекта (3.9) (или полный тип) при закрытии} из класса спецификатора , Внутри класса-класса класс считается полным в телах функций, аргументах по умолчанию и конструкторах-инициализаторах (включая такие вещи во вложенных классах). В противном случае он считается неполным в пределах своей спецификации класса.

Не знаю, что это UINT16, но должно работать

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: 
}; 

EDIT 3: *** пришел туда, пытаясь внести изменения BOLD (который я должен был удален в любом случае)

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

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

Какова цель 'typename' keywork в определении' getNewSValue'? Это потому, что SValue не имеет названия, и мы должны ссылаться на него с помощью имени 'typedef'? –

+0

@Cedric, если мы опустим 'typename', он будет разбираться как определение члена, называемого' SValue' класса 'CClass ', для которого не указан тип: tempate Класс :: SValue; '. Следующие токены будут нежелательными и будут отвергнуты компилятором как синтаксические ошибки. Все это связано с тем, что компилятор по умолчанию принимает не-типы, если он не может найти имя во время разбора (т. Е. Он не знает, что такое 'T', так что он не может искать« SValue »). Если вы поместите 'typename',' SValue' правильно рассматривается как имя-имя для члена 'getNewSValue'. –

+0

Введенный код генерирует следующую ошибку: «ошибка C2244:« CClass :: getNewSValue »: невозможно сопоставить определение функции с существующей декларацией« – okami

0

Как насчет пробовать это? он работал на 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

SValue-Type находится внутри пространства имен CClass. Вы должны полностью квалифицировать имя типа за пределами класса.

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

Кроме того, вы должны сделать публикацию SValue общедоступной, если она будет возвращена общедоступным методом.

0

Для записи ничего из них не будет скомпилировано (по крайней мере, на GCC 4.2), как только вызывается вызов getNewSValue(). Поскольку это открытый метод, который возвращает указатель на частный тип, вы получите ошибку компиляции, указав, что SValue is private.

Для того, чтобы это работало, вам необходимо либо сделать SValue общественность, или изменить тип возвращаемого значения getNewSValue() к чему-то, как void*, так как кажется, что вы пытаетесь сделать SValue непрозрачный тип.

1

Поскольку определение функции члена находится в глобальной области видимости, вам необходимо определить его тип возврата с помощью CClass:: для обозначения имени в пределах класса. Кроме того, ключевое слово typename необходимо при обращении к именам типов, вложенным в шаблоны.

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

Кроме того, вложенная структура не имеет названия. Обратите внимание, что в C++ классы и структуры имеют собственные имена, а имя typedef не является именем класса. Вам будет намного лучше избегать typedef.

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

Это очень многословие :-), но Potatos ваш код генерирует следующее err, на строке: typename CClass :: SValue * CClass :: getNewSValue (void) ERROR ---> "ошибка C2899: typename не может использоваться вне объявления шаблона" – okami

+0

@okami: сохраните 'template ' часть. Для менее подробного синтаксиса определите функцию внутри области 'class {}'. Тогда 'typename' и квалификация (по классам-локальным типам) не нужны. – Potatoswatter

Смежные вопросы