【发布时间】:2010-12-31 21:32:46
【问题描述】:
出于教学目的,我一直在尝试实现自己的链表类。
我在迭代器声明中将“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>;
};
List.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:在“Iterator”的实例化中:
trial.cpp:18:从这里实例化
Iterator.h:12:错误:“结构列表”需要模板参数
List.cc:在成员函数'Iterator List::createStartIterator() const [with T = int]'中:
trial.cpp:18:从这里实例化
Iterator.h:14: 错误:'Iterator::Iterator(Node*) [with T = int]' 是私有的
List.cc:120:错误:在此上下文中
似乎它无法识别朋友声明。 我哪里做错了?
【问题讨论】:
-
不要定义自己的 null(或 NULL,或任何相关的)宏。在初始化数据成员的情况下,
0工作得很好。 -
我知道这很丑,只是暂时的。但我很确定 C++ 不允许隐式转换。
-
强制转换永远不会是隐式的,但转换是。 (您可能会说,同一硬币的两面,“转换”也用于命名在其他用途中转换值的方法,但这是一种不同类型的转换。)您需要初始化一个指针是另一个指针合适的类型,或空指针常量;
0是一个非常好的空指针常量(NULL也是,如果你愿意的话)。 -
在一般情况下,您还需要在标头中定义类模板的 (List's) 方法(而不是 List.cc,它不应该在好的代码中#included),因为类模板和函数模板并不是真正的类和函数,它们生成类和函数,并且编译器必须可以使用完整的代码。
标签: c++ templates compiler-errors friend