在C语言学习阶段,我们学过了队列的C语言的实现,但是在C++里面,我们使用泛型实现了实现了队列类的模板,虽然有现成的队列类的模板,但是这对于我们了解怎样用泛型以及泛型编程中的一些需要注意的地方却是受益匪浅,特别是容易忘记的地方。
好了,接下来咱们上代码
首先是 templateclass.h 文件的实现
/*
* author:xizero00
* mail:xizero00@163.com
* date:2011-08-08 01:34:33
* Template Queue Sample 模板队列示例
*/
#ifndef TEMPLATECLASS_H
#define TEMPLATECLASS_H
#include <iostream>
using namespace std;
//Queue的实现类
//这里是特定的模板友元关系,即类可以只授权特定的实例的访问权,即类Queue和类QueueItem是一对一的关系
template<class T> class Queue;
template <class T>
class QueueItem
{
//因为Queue是需要使用到这个不公开接口的类中的成员,所以需要将Queue声明为友元类
friend class Queue<T>;
private:
//复制构造函数
QueueItem<T>( const T &q ): item( q ) , next( 0 ) {}
//元素值
T item;
//指向下一个元素的指针
QueueItem<T> *next;
};
//类模板
template <class T>
class Queue
{
public:
//需要注意的一点是,一般在类中实现的函数都会是内联函数
//使用内联函数的要求是,该函数的代码一般只有几行,并且经常执行
//默认构造函数
//这样的声明也是可以的
//Queue() :head( 0 ) , tail( 0 ) {}
Queue<T>() :head( 0 ) , tail( 0 ) {}
//复制构造函数
//当然这样的声明也是可以的
//Queue( const Queue &q ): head( q.head ) , tail( q.tail ) { copy_elems( q ); }
Queue<T>( const Queue<T> &q) :head( q.head ) , tail( q.tail ) { copy_elem( q ); }
//操作符重载
Queue<T>& operator= ( const Queue<T>& );
//析构函数
~Queue(){ destroy(); }
//获取头节点的元素
T& front() { return head->item; }
//下面这个是const版本的
//const T& front() { return head->item; }
//入队列
void push( const T& );
//出队列
void pop();
//判断是否为空
bool empty() const { return NULL == head; }
//显示队列元素
void ShowElements() ;
private:
//队列的头指针,尾指针,主要用于出入队列用
QueueItem<T> *head;
QueueItem<T> *tail;
//销毁队列数据
void destroy();
//复制元素
void copy_elems( const Queue& );
};
//出队列,即删除队列头部的元素
template<typename T>
void Queue<T>::pop()
{
//判断是否为空指针
if( NULL == head )
{
return;
}
//保存当前指针的值
QueueItem<T> *p = head;
//将头指针指向下一个元素
head = head->next;
//删除
delete p;
}
//入队列,即从队列的尾部插入数据
template<typename T>
void Queue<T>::push( const T &t )
{
//构造一个对象
QueueItem<T> *p = new QueueItem<T>( t );
//在插入队列尾部的时候需要判断队列是否为空的!
if( empty() )
{
head = tail = p;
}
else
{
//将尾指针的指向下一个元素的指针指向生成的数据
tail->next = p;
//将尾指针移动到最后一个数据上去
tail = p;
}
}
//销毁数据
template<typename T>
void Queue<T>::destroy()
{
//不断地出队列即可
while( !empty() )
{
pop();
}
}
//赋值操作符重载
template<typename T>
Queue<T>& Queue<T>::operator= (const Queue<T> &q)
{
//复制队列元素,结束条件是head为空的时候
for( QueueItem<T> *p= q.head ; p ; p = p->next )
{
push( p->item );
}
}
template<typename T>
void Queue<T>::ShowElements()
{
cout << "当前队列元素为:" << endl;
if( !head )
{
cout << "oops,当前队列为空...." << endl;
}
for( QueueItem<T> *p = head ; p ; p = p->next )
{
cout << p->item << endl;
}
}
#endif //TEMPLATECLASS_H
否则当你在类的外面实现的时候会忘记写模板参数。
好了接下来看 templatesample.cc文件
/*
* author:xizero00
* mail:xizero00@163.com
* date:2011-08-08 01:34:33
* Template Queue Sample 模板队列示例
*/
#include "templateclass.h"
int main( int argc , char **argv )
{
Queue<int> q;
int data[] = { 1, 2, 4 ,5 };
//入队列
for( int i = 0 ; i < 4 ; i++ )
{
q.push( data[i] );
}
cout << "q队列元素如下:" << endl;
q.ShowElements();
Queue<int> p;
//复制队列元素
p = q;
cout << "p队列元素如下(它是复制的q队列的元素):" << endl;
p.ShowElements();
cout << "对p队列进行出队列操作" << endl;
p.pop();
p.ShowElements();
cout << "出队列操作进行3次" << endl;
p.pop();
p.pop();
p.pop();
p.ShowElements();
return 0;
}
下面给出编译所需的Makefile
# author:xizero00
# mail:xizero00@163.com
# date:2011-08-08 01:37:39
# Makefile for Template Queue Sample 模板队列示例
compile:
g++ templatesample.cc -g -o template
./template
clean:
rm -f template
ls -al template*
q队列元素如下:
当前队列元素为:
1
2
4
5
p队列元素如下(它是复制的q队列的元素):
当前队列元素为:
1
2
4
5
对p队列进行出队列操作
当前队列元素为:
2
4
5
出队列操作进行3次
当前队列元素为:
oops,当前队列为空....
总结:在学习模板类的时候,我想最重要的还是需要动手,其次是养成良好的编码习惯,能够让你的注释清晰易懂,让你的理解也能够让别人理解,代码看起来清清爽爽的才是最终目的,学习的目的就是和他们分享,一起进步!