2010-04-13 128 views
4

我有一個模板和指針問題(我認爲)。下面是我的代碼的一部分:C++模板和指針

/* ItemCollection.h */ 

#ifndef ITEMCOLLECTION_H 
#define ITEMCOLLECTION_H 

#include <cstddef> 

    using namespace std; 

    template <class T> class ItemCollection 
    { 
    public: 
    // constructor 
     //destructor 

    void insertItem(const T); 

    private: 
     struct Item 
     { 
      T price; 
      Item* left;    
      Item* right;   
     }; 
     Item* root;  
     Item* insert(T, Item*); 

    }; 
#endif 

而且具有功能確定指標的文件:

/* ItemCollectionTemp.h-member functions defintion */ 

#include <iostream> 
#include <cstddef> 

#include "ItemCollection.h" 

template <class T> 
    Item* ItemCollection <T>::insert(T p, Item* ptr) 
    { 
     // function body 
    } 

以下是這是由下面這行代碼生成的錯誤:

Item* ItemCollection <T>::insert(T p, Item* ptr) 

錯誤:

錯誤C2143:語法錯誤:缺少';'之前'*'

錯誤C4430:缺少類型說明符 - int假定。注意:C++不支持默認int

錯誤C2065: '類型':未聲明的標識符

錯誤C2065:前缺少 ')': '類型':未聲明的標識符

錯誤C2146:語法錯誤標識符'p'

錯誤C4430:缺少類型說明符 - 假定爲int。注意:C++不支持default-int

錯誤C2470:'ItemCollection :: insert':看起來像一個函數定義,但沒有參數列表;跳過表觀體

錯誤C2072: 'ItemCollection ::插入':語法錯誤:: ')'

任何幫助非常感謝函數

錯誤C2059的初始化。

+0

@Kary:既然你要求解釋阿列克謝的答案,記住你不應該接受一個答案,除非你真的對此感到滿意。如果你想要更多的細節,那就說,不要接受它。或者接受另一個答案,它提供了你想要的細節。 – jalf 2010-04-13 19:04:40

回答

6
template <class T> 
    typename ItemCollection <T>::Item* ItemCollection<T>::insert(T p, Item* ptr) 
    { 
     // function body 
    } 
+5

也許你可以編輯你所做的更改的解釋? – 2010-04-13 12:16:58

+1

什麼解釋?我只用'typename ItemCollection :: Item * ItemCollection :: insert(T p,Item * ptr)'來替換錯誤的'Item * ItemCollection :: insert(T p,Item * ptr)''。 – 2010-04-13 12:25:44

+5

我知道,但是對於學習C++的人來說,解釋爲什麼他們的代碼有問題,然後給他們代碼讓他們可以放入以解決問題,這會更有幫助;否則沒有什麼是學習的,他們又回到了同樣的問題。尤其是對於需要使用'typename'關鍵字的情況,這在C++中通常是無法理解的。即使OP瞭解他做錯了什麼,解釋也會幫助那些通過Google找到這個問題的人。 – 2010-04-13 13:14:35

6

簡短的答案是什麼阿列克謝已經發布:

template <typename T> 
typename ItemCollection<T>::Item* ItemCollection<T>::insert(T p, Item * ptr) { 
    // ... 
} 

(要了解爲什麼需要typename,所以搜索相關問題,否則丟棄評論我將專注於答案的。查找規則解釋了爲什麼返回和參數類型必須以不同的方式聲明)

解釋是C++中的查找規則對於返回類型和其餘參數具有不同的作用域。當編譯器看到定義A B::c(D)時,將在定義的封閉名稱空間中檢查A,如同B。當編譯器發現::c時,它在類B內查找c。在這一點上,其餘的定義在其他參數的類B的範圍內。這意味着如果返回類型是類的內部類型,則必須使用返回類型的限定名稱,而在D的情況下,編譯器將首先在類B內查找它。

這解釋了爲什麼返回類型必須完全限定,即使最後一個參數不是。當編譯器找到參數Item * ptr時,它已經在類的範圍內,並且它會在那裏找到它。另一方面,在封閉名稱空間中沒有定義Item

上升標準中的一個變化將解決這個問題,即使它不是爲了這個目的而設計的。如果我沒有記錯,下面的語法應該在沒有完整類型限定的情況下編譯:

template <T> 
auto ItemCollection<T>::insert(T p, Item * ptr) -> Item * 
{ 
    return 0; 
} 

原因完全相同。 ItemCollection<T>::insert已被解析後,餘下的令牌將在ItemCollection<T>範圍內進行驗證,包括-> Item *返回定義。