2010-01-03 122 views
12

为了教学目的,我一直在尝试实现自己的链表类。在模板类中声明模板好友类时发生编译器错误

我在Iterator声明中指定了“List”类作为朋友,但它似乎没有编译。

这是我用过的3个班的接口:

Node.h:

#define null (Node<T> *) 0 

template <class T> 
class Node { 
public: 
    T content; 
    Node<T>* next; 
    Node<T>* prev; 

    Node (const T& _content) : 
     content(_content), 
     next(null), 
     prev(null) 
    {} 
}; 

Iterator.h:

#include "Node.h" 

template <class T> 
class Iterator { 
private: 
    Node<T>* current; 

    Iterator (Node<T> *); 

public: 
    bool isDone() const; 

    bool hasNext() const; 
    bool hasPrevious() const; 
    void stepForward(); 
    void stepBackwards(); 

    T& currentElement() const; 

    friend class List<T>; 
}; 

名单。 h

#include <stdexcept> 
#include "Iterator.h" 

template <class T> 
class List { 
private: 
    Node<T>* head; 
    Node<T>* tail; 
    unsigned int items; 

public: 
    List(); 

    List (const List<T>&); 
    List& operator = (const List<T>&); 

    ~List(); 

    bool isEmpty() const { 
     return items == 0; 
    } 
    unsigned int length() const { 
     return items; 
    } 
    void clear(); 

    void add (const T&); 
    T remove (const T&) throw (std::length_error&, std::invalid_argument&); 

    Iterator<T> createStartIterator() const throw (std::length_error&); 
    Iterator<T> createEndIterator() const throw (std::length_error&); 
}; 

这是测试程序中,我一直在试图运行:

trial.cpp

using namespace std; 
#include <iostream> 
#include "List/List.cc" 

int main() 
{ 
List<int> myList; 

for (int i = 1; i <= 10; i++) { 
    myList.add(i); 
} 

for (Iterator<int> it = myList.createStartIterator(); !it.isDone(); it.stepForward()) { 
    cout << it.currentElement() << endl; 
} 

return 0; 
} 

当我尝试编译,编译器给了我下面的错误:

Iterator.h:26:错误: '名单' 是不是一个模板

Iterator.h:在 '迭代器' 的实例:

trial.cpp:18:从这里

Iterator.h实例:12:错误:所需模板参数“结构列表“

List.cc:在成员函数 '迭代一览:: createStartIterator()const的[与T = INT]':

trial.cpp:18:从这里

Iterator.h实例:14:错误:迭代::迭代器(节点*)[用T = INT]'是私人

表.cc:120:错误:在这种情况下

似乎它不认识朋友声明。 我哪里错了?

+0

不要定义您自己的null(或NULL或任何相关的)宏。在初始化数据成员的情况下,'0'工作得很好。 – 2010-01-03 00:46:15

+0

我知道这很丑,只是暂时的。但我确信C++不允许隐式转换。 – 2010-01-03 00:48:20

+0

演员绝不隐含,但转换是。 (您可能会说,同一枚硬币的两面,“转换”也用于命名将值转换为其他用途的方法,但这是另一种类型的转换。)需要初始化指针的另一个指针合适的类型或空指针常量; '0'是一个非常好的空指针常量(如果你愿意,'NULL'也是如此)。 – 2010-01-03 00:52:32

回答

15

尝试在Iterator.h开始加入预先声明

template <class T> class List; 

- 这可能是你所需要的,让friend声明Iterator类的内部工作。

+0

谢谢!这对我有效。 – sgowd 2015-12-05 01:01:03

5

问题是List没有在Iterator.h中正确声明。相反,将Iterator类嵌套到List中(自动将它作为模板),无论如何您可能会想要这样做(使用List :: Iterator而不是将其重命名为ListIterator或IteratorForList,因为您将有多个Iterator在命名空间中)。

template<class T> 
struct List { 
    //... 
    struct Node {/*...*/}; 
    struct Iterator { 
    // ... 
    private: 
    Iterator(Node*); 
    friend class List; // still required 
    }; 
    //... 
};