2010-04-13 131 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 *返回定义。