Queue的实现:
1. 模板类定义
#include <iostream>
// 知识点:声明Queue模板类, 第三行的友类声明才成立
template<typename Type> class Queue;
template<typename Type> std::ostream& operator<<(std::ostream&, Queue<Type>&);
template<typename Type> class QueueItem {
// 知识点: 限制其他类型的Queue<OtherType>访问 QueueItem
friend class Queue<Type>;
friend std::ostream& operator<<<Type>(std::ostream&, Queue<Type>&); // 知识点:友元函数模板
QueueItem(const Type& t) : item(t), next(0) {}
Type item;
QueueItem* next;
};
template<class Type> class Queue {
friend std::ostream& operator<< <Type>(std::ostream&, Queue<Type>&);
public:
Queue() : head(0), tail(0) {}
Queue(const Queue&q):head(0),tail(0){ // 知识点: Queue(const Queue<Type>&)
copy_elems(q);
}
template<typename It>Queue(It start, It end): head(0),tail(0) {
assign(start, end);
}
~Queue() { destroy(); }
// 知识点:等效于 Queue<Type>& operator=(const Queue<Type>&);
Queue& operator=(const Queue&);
Type& front() { return head->item; }
const Type& front() const{ return head->item; }
void push(const Type&);
void pop();
template<typename It> void assign(It start, It end);
bool empty() { return head == 0; }
private:
QueueItem<Type>* head;
QueueItem<Type>* tail;
void destroy();
void copy_elems(const Queue&);
};
2. 模板类内函数定义
template<class Type> Queue<Type>& Queue<Type> ::operator=(const Queue& q) {
destroy();
copy_elems(q);
return *this;
}
// 知识点 :operator << <Type>
template<typename Type> std::ostream& operator<< <Type>(std::ostream& os, Queue<Type>& q) {
QueueItem<Type>* ptr = q.head;
os << "[";
while (ptr) {
os << ptr->item;
ptr = ptr->next;
if (ptr)
os << ",";
}
os << "]";
return os;
}
// 知识点:不恰当举例,为了说明模板类中的模板函数在类外的定义方式
template<typename type>template<typename It> void Queue<type>::assign(It start, It end) {
while (start != end)
push(*start++);
}
template<class Type> void Queue<Type>::push(const Type& val) {
QueueItem<Type> *pt = new QueueItem<Type>(val);
if (empty())
head = tail = pt;
else {
tail->next = pt;
tail = pt;
}
}
template<class Type> void Queue<Type>::pop() {
QueueItem<Type> * p = head;
head = head->next;
delete p;
}
template<class Type> void Queue<Type>::copy_elems(const Queue&orig) {
for (QueueItem<Type> *pt = orig.head; pt; pt = pt->next)
push(pt->item);
}
template<class Type> void Queue<Type>::destroy() {
while (!empty())
pop();
}
注意点:
引用于:点击打开链接
1.在定义友元之前,我们对友元进行了声明。之前为一个类定义普通友元的时候,是无须声明的。这里必须对其声明的原因在于:我们定义的友元,也是模板。如果不声明,会是得友元函数和友元类的所有实例都能访问类的私有成员。当我们的QueueItem的内容是string型时,让Queue<int>类型也能访问是不合适的。
2. 由于类实例化时已经确定了成员函数的类型,所以这里不需要再进行模板实参推断了,这与普通函数模板不一样。当调用函数的实参与模板实例化后的形参不完全匹配时,可以会发生常规类型转换;不像函数模板,如果不匹配则出现错误。
举例:对于Queue<int> q,你仍然可以short sh = 4; q.push(sh);