template的用法(转载)---希望对大家有用

来源:互联网 发布:汉服好的淘宝店铺推荐 编辑:程序博客网 时间:2024/05/16 00:25

--  template 的用法
在程式设计当中经常会出现使用同种数据结构的不同实例的情况。例如:在一个程式中
能使用多个队列、树、图等结构来组织数据。同种结构的不同实例,也许只在数据元素
的类型或数量上略有差异,如果对每个实例都重新定义,则非常麻烦且容易出错。那么能
否对同种类型数据结构仅定义一次呢?答案是肯定的,C++提供的类模板(Class Template
)就能实现该功能。
一、类模板
类模板是C++提供的一种特别机制,通过他我们能定义一种特别的类(称为模板类),在类
的定义中能包含待定的类型参数,在声明类的实例时,系统会自动根据传递的类型生成
用户想要生成的类实例。下面是用C++实现的一个简单的模板类Clist的定义。
Template <class T, int I> class CList
{
public:
int SetItem(int Index, const T &Item);
int GetItem(int Index, T &Item);
private:
T Buffer;
}
在这里,T是类型参数,I是整型常量参数。T和I的实际值是在声明具体类实例时指定的。
模板类的<>号内能包括任意个类型参数和常量参数(至少要有一个参数)。类型参数和
常量参数能是所有合法的标准类型和用户自定义类型,包括简单类型及各种结构体。同
其他类相同,类成员函数SetItem的实现能在类定义内完成,也能在类CList定义处实
现:
template<class T, int I> int CList<T, I>::SetItem(int Index, const T &Item)
{
if ( (Index<0)||(Index>I-1) )
 return 0; // 出错
Buffer[Index]= Item ;
 return 1; // 成功
}
值得注意的是,在类定义外完成函数实现时,必须以关键字template和类模板定义中相同
的参数表(<>号内的)开头(上例为template<class T, int I>),并且范围分解操作符前的
类名后应跟上模板参数名清单(上例为CList<T, I>)。另外,和非模板类不同的是,必须将
函数实现包括在调用他的每个源文件中,使编译器能从函数实现产生代码。通常的做法是
将模板类的函数实现也放在定义该类的头文件中,这样只需在调用的源文件中包含该头文
件即可。
那么,怎么使用生成特定的类实例呢?我们能像使用其他类相同来使用模板类,不过必须
指定模板参数的值。例如采用如下声明:
CList <int, 100> IntList;
则使IntList成为CList类的实例,每次出现的T参数都换成int, 每次出现的I参数都换成
100。这样,IntList类中的Buffer就是个长度为100的整型数组,SetItem和GetItem函数
参数是int值的引用。例:
IntList.SetItem(0, 5); //给数组第一个元素赋为整数5
模板类还能像其他类相同能定义构造函数和析构函数。下面我们以一种简单的数据
结构??堆栈为例,来说明怎么用类模板来构造通用数据结构。
二、 利用类模板实现通用堆栈结构
所有抽象数据结构在计算机中的实现,归根结底都只有两种方式:顺序存储(用数组实现)
,链式存储(用指针实现)。堆栈也不例外,按其实现方式可分为顺序栈(用数组实现)和链
栈(用指针实现)。
1. 通用顺序栈的实现
因为顺序栈中的元素在空间上连续存储,栈顶的元素位置需要注明,所以构造顺序栈的模
板类应该有这样的一些成员变量:一个待定类型和长度的数组Buffer,一个记录栈顶元素
的数组下标的整型变量top。堆栈的基本操作主要有:入栈(Push)、出栈(Pop)、置空(Se
tEmpty)、判断当前状态(IsEmpty)等,他们应用模板类的成员函数来实现。作为一个标准
的类,他还应该有自己的构造函数和析构函数。具有这些功能的模板类,就能作为一个
通用的顺序栈来使用了。该类的定义如下:
template <class T,int SIZE> class CArrayStackTemp
{
public:
CArrayStackTemp () //缺省构造函数,构造一个空堆栈
{
top= -1;
};
~ CArrayStackTemp (){};//析构函数
 void SetEmpty (); //置空堆栈
 bool IsEmpty(); //判断堆栈是否为空
 bool Push(T element); //入栈
 bool Pop(T& element);//出栈
private:
T Buffer[SIZE];
 int top;
};
和堆栈的基本操作相对应的成员函数的实现如下:
template <class T, int SIZE> void CArrayStackTemp<T, SIZE>:: SetEmpty ()
{
top= -1; //将栈顶指针赋 -1,并不实际清除数组元素
}
template <class T, int SIZE> bool CArrayStackTemp<T, SIZE>:: IsEmpty ()
{
return(top == -1);
}
template <class T, int SIZE> bool CArrayStackTemp<T, SIZE>:: Push (T element
)
{
top++;
if (top>SIZE-1)
{
top--;
return false; //堆栈已满,不能执行入栈操作
}
Buffer[top]=element;
return true;
}
template <class T, int SIZE> void CArrayStackTemp<T, SIZE>:: Pop (T& element
)
{
if (IsEmpty())
 return false;
element =Buffer[top];
top--;
return true;
}
根据实际需要,还能扩充堆栈功能。例如:加入取栈顶元素、求堆栈长度等操作,其方法
如上。
2. 通用链栈的实现
模板类中允许使用指针和定义自己的结构,这就为实现链式结构提供了确保。这里采用一
个单链表来实现堆栈,栈顶指针指向链表的第一个结点,入栈和出栈均在链表的头进行。
该模板类的定义如下:
template <class T> class CLinkStackTemp
{
public:
 //类的缺省构造函数,生成一个空堆栈
CLinkStackTemp ()
{
top=NULL;
};
~ClinkStackTemp(){}; //析构函数
 //定义结点结构
 struct node
{
T
  data; //入栈元素
 node* next; //指向下一结点的指针
};
 void SetEmpty(); //置空堆栈
 bool IsEmpty(); //判断堆栈是否为空
 bool Push(T element); //压入堆栈
 bool Pop(T& element);//弹出堆栈
private:
 node* top;
};
该类的成员函数实现如下:
template <class T> void CLinkStackTemp <T>::SetEmpty()
{
//释放堆栈占用的内存
node* temp;
while (top!=NULL)
{
 temp=top;
 top=top->next;
 delete temp;
}
}
template <class T> bool CLinkStackTemp <T>::IsEmpty()
{
return (top==NULL);
}
template <class T> bool CLinkStackTemp <T>::Push(T element)
{
node* temp=new node();
if (temp ==NULL)
 return false ;
temp->data=element;
temp->next=top;
top=temp;
return true;
}
template <class T> bool CLinkStackTemp <T>::Pop(T& element)
{
if ( IsEmpty())
 return false;
node* q = top;
element = top->data;
top=top->next;
delete q;
return true;
}
和顺序栈的实现略有不同,链栈不必指定栈的容量,其大小能是近似"无限"的。为了程
序的使用方便,我们同样能加入一些增强的功能。
三、 通用堆栈类的使用
通用堆栈类的使用较为简单,堆栈类的实例就是个能方便使用的堆栈。对堆栈的操作
都是通过类的成员函数来实现的。使用的具体步骤如下:
1. 在要使用堆栈类的程式代码的文件开头包括模板类及其成员函数的定义。
2. 类的实例化,可声明成变量,也能声明他的指针,如:
CArrayStackTemp <int, 100> intStack; //生成一个长度为100的int型堆栈
//生成一个元素为Record型的堆栈,Record为自定义结构
CLinkStackTemp <Record>* RecordStack;
RecordStack=new CLinkStackTemp<Record>;
应注意在定义顺序栈时,必须指定栈的大小,而链栈则不必。另外在指定指针类型和执行
new操作时,必须对模板参数赋值,并且前后要一致。
3. 对堆栈进行操作,如:
intStack.Push(3); //将整数3入栈
RecordStack.SetEmpty(); //将堆栈置空
无论我们使用哪种堆栈类,对用户来讲都是透明的,操作起来并无差别。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 玻璃瓶的塑料盖子打不开怎么办 泡酒玻璃瓶盖子打不开怎么办 罐头的塑料瓶盖打不开怎么办 塑料水杯盖紧了怎么办 拧不开矿泉水瓶盖怎么办 新暖壶盖吸住了怎么办 暖瓶盖被吸住了怎么办 做面包和面粘手怎么办 面包面和稀了怎么办 鱼缸氧气泵声音大怎么办 中班安全遇到火灾怎么办反思 汤洒了怎么办活动反思 下水道被塑料盖堵了怎么办 卫生间地漏盖子掉到下水道怎么办 洗手池下水道翻盖打不开了怎么办 培乐多彩泥吃了怎么办 超轻橡皮泥干了怎么办 脑梗脾气大怎么办好啊 牙齿喝饮料烂了怎么办 大门牙缝里黑了怎么办 椰汁拧不开瓶盖怎么办 装蜂蜜的玻璃罐打不开怎么办 蚂蚱没有草吃了怎么办 笔记本电源已接通未充电怎么办 电源已接通未充电怎么办 遮盖纹身好了颜色淡了怎么办 致炫方向盘变重怎么办 xp音频图标没了怎么办 狙击精英3没子弹怎么办 干活干的手腕疼怎么办 干了活不给钱怎么办 干了活要不到钱怎么办 活干完了钱不给怎么办 微信语音聊天音量很小怎么办 一手软件崩溃钱卡住了怎么办 身上皮肤很黑怎么办?好想穿短裙 家里有很多小飞虫怎么办 家里有垃圾中飞出虫子怎么办 雷蛇笔记本很烫怎么办 登录监控器的账号锁了怎么办 悦借钱登录账号被锁怎么办