2010-09-06 22 views
5

Với mã này (chỉ cần một lớp học thử nghiệm):Làm thế nào để có một Struct với mẫu với một lớp

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

tôi có các lỗi sau đây:

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

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

Có thể sử dụng một Cấu trúc trong một lớp học? Nếu tôi khai báo cấu trúc ra khỏi lớp, mẫu không thấy mẫu T.

+2

+1: câu hỏi có định dạng độc đáo – Chubsdad

Trả lời

0

Dường như struct của bạn không được xác định khi bạn khai báo loại trả về là getNewSValue.

Với rằng bạn không phải là lỗi:

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

Và bạn cũng phải hội đủ điều kiện loại SValue trở lại, bởi vì nó được lồng trong CClass khi bạn sử dụng nó để xác định getNewSValue.

0

Declare SValue trước getNewSValue():

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

Ngoài ra, hãy chắc chắn UInt16 được định nghĩa.

3

$ 9,2/2- Điều quan trọng là dưới đây trích dẫn từ C++ Standard03

'Một lớp được coi là một loại hoàn toàn xác định đối tượng (3,9) (hoặc gõ đầy đủ) vào lúc kết thúc} của lớp-specifier . Trong lớp đặc tả thành viên, lớp được coi là hoàn chỉnh bên trong các cơ quan hàm, các đối số mặc định và các hàm khởi tạo của hàm dựng (bao gồm các thứ như vậy trong các lớp lồng nhau). Nếu không, nó được coi là không đầy đủ trong đặc tả thành viên lớp học của riêng nó.

Không biết là những gì UINT16, nhưng sau nên làm việc

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: *** đã có cố gắng để thực hiện thay đổi BOLD (mà tôi nên đã xóa anyways)

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

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

Mục đích của 'typename' keywork trong định nghĩa' getNewSValue' là gì? Đó là vì SValue không được đặt tên và chúng ta phải tham khảo nó bằng tên 'typedef'? –

+0

@Cedric nếu chúng ta bỏ qua 'typename', nó sẽ được phân tích cú pháp như định nghĩa của một thành viên có tên là' SValue' của lớp 'CClass ', mà không có kiểu nào được chỉ định: 'tempate Class :: SValue;'. Các mã thông báo sau sẽ là rác và bị từ chối bởi trình biên dịch dưới dạng lỗi cú pháp. Điều này tất cả là vì trình biên dịch mặc định giả định không phải là loại nếu nó không thể tra cứu một tên tại thời gian phân tích (nghĩa là nó không biết 'T' là gì, vì vậy nó không thể tra cứu' SValue'). Nếu bạn đặt 'typename',' SValue' được coi là một tên tập tin cho thành viên 'getNewSValue'. –

+0

Mã bạn đặt tạo ra lỗi sau: "lỗi C2244: 'CClass :: getNewSValue': không thể khớp định nghĩa hàm với khai báo hiện tại" – okami

0

thử cách này? nó hoạt động trên 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

Loại SValue nằm bên trong không gian tên CClass. Bạn cần phải hoàn toàn đủ điều kiện tên tệp bên ngoài lớp học.

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

Ngoài ra, bạn nên chắc SValue công cộng, nếu nó được trả về bởi một phương pháp nào.

0

Đối với bản ghi, không có bản ghi nào trong số này sẽ biên dịch (ít nhất trên GCC 4.2) ngay sau khi gọi đến số getNewSValue() được gọi. Vì đây là phương thức công khai trả về con trỏ cho một loại riêng tư, bạn sẽ nhận được lỗi biên dịch cho biết rằng SValue is private. Để làm việc này, bạn sẽ cần phải đặt SValue công khai hoặc thay đổi loại giá trị trả lại là getNewSValue() thành một cái gì đó như void*, vì có vẻ như bạn đang cố gắng làm cho SValue trở thành một loại mờ.

1

Vì định nghĩa hàm thành viên nằm trong phạm vi toàn cục, bạn cần phải đủ điều kiện loại trả về của nó với CClass:: để tham chiếu đến tên trong phạm vi lớp học. Ngoài ra, các từ khóa typename là cần thiết khi đề cập đến tên tập tin lồng nhau trong các mẫu.

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

Ngoài ra, cấu trúc lồng nhau không được đặt tên. Lưu ý rằng trong C++, các lớp và cấu trúc có tên riêng và tên typedef không phải là tên lớp. Bạn sẽ được tốt hơn nhiều off tránh typedef.

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

Điều này rất chi tiết :-), nhưng Potatos mã của bạn tạo ra lỗi sau, trên dòng: typename CClass :: SValue * CClass :: getNewSValue (void) ERROR ---> "lỗi C2899: không thể sử dụng tên tệp bên ngoài khai báo mẫu" – okami

+0

@okami: giữ phần 'mẫu '. Đối với cú pháp ít chi tiết hơn, hãy định nghĩa hàm bên trong phạm vi 'class {}'. Sau đó, 'typename' và trình độ chuyên môn (trên các loại lớp địa phương) là không cần thiết. – Potatoswatter

Các vấn đề liên quan