模板类声明,类模板的实例化

C\C++作为强类型语言,变量和函数参数、返回值是一定要声明类型模板类声明的,对于某些算法来说,除模板类声明了数据类型不同以外,其它代码(逻辑)都是一样模板类声明的。

模板类声明我们希望能够将这些通用性较强的算法做成模板(Template),只需要填入相应的数据类型,就能立刻可用。

模板类声明

C++中的模板分为两种模板类声明:函数模板和类模板,分别适用于面向过程和面向对象的程序设计。

1 函数模板

函数模板是一系列相关函数的模型或样板,这些函数的源代码形式相同,只是所针对的数据类型不同。对于函数模板,数据类型本身成了它的参数,因而是一种参数化类型的函数。

函数模板与普通函数相似,也有函数模板原型、函数模板头、函数模板体。

函数模板的原型为:

template <数据类型参数表> 返回值类型 函数名(参数表);例如:template <class T,class U>U func(T a,int b,U c);

数据类型参数是一种特殊的参数,其填入的实参并不是一个数据,而是一种数据类型,如int、char。

在数据类型参数的作用域之内,该参数的标识符就用来代表一种数据类型。

两个变量或存储区域的数据交换与数据的类型无关,无论整型、浮点型、字符型都可以进行数据交换。

尽管如此,当两个字符串(字符数组)进行交换时,与两个普通的变量交换又有所不同。(字符数组做为函数参数时,数组名是一个常量指针,不能用作左值。)

对于绝大多数变量,采用函数模板的方式实现交换。

对于字符串(字符数组),采用重载函数的方式实现交换。

实例代码:

模板类声明

运行结果:

交换后为2,3

交换后为b,a

交换后为Shanghai University,Tomato Studio

在C++中,函数模板与重载可以同时使用。只要使该函数模板的名称与重载函数的名称相同即可。

当调用一个函数时,优先调用重载函数。如果没有重载,则查找是否有同名的函数模板,并根据调用时实参的类型依照函数模板生成一个“临时”的重载函数后调用。

实例代码:

模板类声明

运行结果:

8

2.65

Tomato Studio

Tomato

2 类模板

类模板就是一系列相关类的模板或样板,这些类的成员组成相同,成员函数的源代码形式相同,所不同的只是针对的类型(数据成员的类型以及成员函数的参数和返回值的类型)。对应类模板,数据类型本身成了参数,因而是一种参数化类型的类,是类的生成器。类模板中声明的类称为模板类。

模板类声明

与普通的类相似,类模板也需要声明和定义。声明一个类模板的 *** 为:

template <数据类型参数表> class 类模板名;例如:template <class T> class Buffer;

类模板通常应用于对各种数据类型适用的数据存储类。例如链表类、向量(数组)类、栈类等。

通过使用链表类模板,可以创建出存储整型的链表、存储字符的链表以及存储字符串的链表。

类模板的定义与类的定义相似,但在某些合适的地方将具体的数据类型改为数据类型参数。例如:

模板类声明

对于在类模板定义内定义的成员函数,与一般的成员函数在类定义内的定义方式一致。

对于在类模板定义外定义的成员函数,格式为:

template <数据类型参数表> 返回值类型 模板名<类型参数顺序表>::成员函数名(参数表) { 语句1; 语句2; …… }

在使用类模板时,先要填入对应的数据类型参数,使其变成一个完整的类,然后再用这个类来创建一个对象。因此,用类模板创建一个对象的 *** 为:

类模板名<数据类型列表> 对象名(初始化数据);

实例代码:

模板类声明

运行效果:

请输入一个整数:4Node constructor is running...Linklist constructor is running...Node constructor is running...Node constructor is running...After Linklista Insert421请输入一个字符:eNode constructor is running...Linklist constructor is running...Node constructor is running...Node constructor is running...After Linklist b InsertePC

附代码1:

#include <iostream>using namespace std;template <class T> void Swap(T &a,T &b);void Swap(char a[],char b[]);int main(){ int a=3,b=2; //int和char变量用函数模板实现交换 char c='a',d='b'; char s1[32]="Tomato Studio"; //字符数组要用重载函数实现交换 char s2[32]="Shanghai University"; Swap(a,b); //调用函数模板 cout <<"交换后为" <<a <<"," <<b <<endl; Swap(c,d); //调用函数模板 cout <<"交换后为" <<c <<"," <<d <<endl; Swap(s1,s2); //调用重载函数 cout <<"交换后为" <<s1 <<"," <<s2 <<endl; system("pause"); return 0;}template <class T> void Swap(T &a,T &b){ T temp=a; //简单交换 a=b; b=temp; return;}void Swap(char a[],char b[]){ int i; char temp[32]; //临时数组 for (i=0;a[i]!='\0';i++) temp[i]=a[i]; //所有a数组元素复制到temp数组 temp[i]='\0'; //填补结尾符 for (i=0;b[i]!='\0';i++) a[i]=b[i]; //所有b数组元素复制到a数组 a[i]='\0'; for (i=0;temp[i]!='\0';i++) b[i]=temp[i]; //所有temp数组元素复制到b数组 b[i]='\0'; return;}

附代码2:

#include <iostream>#include <string>using namespace std;template <class T>T *** aller( T a, T b ) /* 函数模板 */{ if ( a <= b ) { return(a); }else { return(b); }}char * *** aller( char *a, char *b ) /* 重载函数 */{ if ( strlen( a ) <= strlen( b ) ) /* strlen函数返回字符串的长度 */ { return(a); }else { return(b); }}int main(){ cout << *** aller( 8, 22 ) << endl; cout << *** aller( 99.88, 2.65 ) << endl; cout << *** aller( "Tomato Studio", "Shanghai University" ) << endl; cout << *** aller( "Tomato", "tomato" ) << endl; system( "pause" ); return(0);}

附代码3:

//3个文件

//main.cpp

//linklist.h

//node.h

//main.cpp

#include "linklist.h"

#include <iostream>

using namespace std;

int main()

{

int tempi;

char tempc;

cout <<"请输入一个整数:" <<endl;

cin >>tempi;

Linklist<int> a(tempi); //创建模板类对象时一定要注明类型

a.Locate(tempi);

a.Insert(1); //参数为int类型

a.Insert(2);

cout <<"After Linklista Insert" <<endl;

a.Show();

cout <<"请输入一个字符:" <<endl;

cin >>tempc;

Linklist<char> b(tempc); //创建模板类对象时一定要注明类型

b.Locate(tempc);

b.Insert('C'); //参数为char类型

b.Insert('P');

cout <<"After Linklist b Insert" <<endl;

b.Show();

system("pause");

return 0;

}

//linklist.h

#include "node.h"

#include <iostream>

using namespace std;

template <class T> class Linklist

{

public:

Linklist(T a);

Linklist(Linklist<T> &l); //拷贝构造函数

~Linklist();

bool Locate(T a); //参数的数据类型由T决定

bool Insert(T a);

bool Delete();

void Show();

void Destroy();

private:

Node<T> head;

Node<T> * pcurrent;

};

//链表类模板的构造函数

template <class T> Linklist<T>::Linklist(T a):head(a)

{

cout <<"Linklist constructor is running..." <<endl;

pcurrent=&head;

}

template <class T> Linklist<T>::Linklist(Linklist<T> &l):head(l.head)

{

cout <<"Linklist Deep cloner running..." <<endl;

pcurrent=&head;

Node<T> * ptemp1=l.head.next; //创建模板类对象时一定要注明类型

while(ptemp1!=NULL) //逐一拷贝结点的data

{

Node<T> * ptemp2=new Node<T>(ptemp1->data,pcurrent,NULL);

pcurrent->next=ptemp2;

pcurrent=pcurrent->next;

ptemp1=ptemp1->next;

}

}

template <class T> Linklist<T>::~Linklist()

{

cout <<"Linklist destructor is running..." <<endl;

Destroy();

}

// 节点查找

template <class T> bool Linklist<T>::Locate(T a)

{

Node<T> * ptemp=&head;

while(ptemp!=NULL)

{

if(ptemp->data==a)

{

pcurrent=ptemp;

return true;

}

ptemp=ptemp->next;

}

return false;

}

// 节点插入

template <class T> bool Linklist<T>::Insert(T a)

{

if(pcurrent!=NULL)

{

Node<T> * temp=new Node<T>(a,pcurrent,pcurrent->next);//先连

if (pcurrent->next!=NULL)

{

pcurrent->next->prior=temp; //后断

}

pcurrent->next=temp; //后断

return true;

}

else

{

return false; //插入失败

}

}

template <class T> bool Linklist<T>::Delete()

{

if(pcurrent!=NULL && pcurrent!=&head)

{

Node<T> * temp=pcurrent;

if (temp->next!=NULL)

{

temp->next->prior=pcurrent->prior; //先连

}

temp->prior->next=pcurrent->next; //先连

pcurrent=temp->prior;

delete temp; //后断

return true;

}

else

{

return false;

}

}

template <class T> void Linklist<T>::Show()

{

Node<T> * ptemp=&head;

while (ptemp!=NULL) //链表的遍历

{

cout <<ptemp->data <<endl;

ptemp=ptemp->next;

}

}

template <class T> void Linklist<T>::Destroy()

{

Node<T> * ptemp1=head.next;

while (ptemp1!=NULL) //逐一删除结点对象

{

Node<T> * ptemp2=ptemp1->next;

delete ptemp1;

ptemp1=ptemp2;

}

head.next=NULL;

}

//node.h

#include <iostream>

using namespace std;

template <class T> class Linklist;

//如果要将一个类模板作为友元,必须声明它的存在

template <class T> class Node //定义一个链表结点类模板

{

friend class Linklist<T>; //链表类模板作为友元

public:

Node();

Node(Node<T> &n); //参数是一个模板类对象的引用,<T>不可缺少

Node(T a); //构造函数重载1

Node(T a,Node<T> *p,Node<T> *n); //构造函数重载2

~Node();

private:

T data; //成员数据的类型由类型参数T决定

Node<T> *prior;

Node<T> *next;

};

template <class T> Node<T>::Node()

{

cout <<"Node constructor is running..." <<endl;

prior=NULL;

next=NULL;

}

template <class T> Node<T>::Node(T a)

{

cout <<"Node constructor is running..." <<endl;

data=a;

prior=NULL;

next=NULL;

}

template <class T> Node<T>::Node(T a,Node<T> *p,Node<T> *n)

{

cout <<"Node constructor is running..." <<endl;

data=a;

prior=p;

next=n;

}

template <class T> Node<T>::Node(Node<T> &n)

{

data=n.data;

prior=n.prior;

next=n.next;

}

template <class T> Node<T>::~Node()

{

cout <<"Node destructor is running..." <<endl;

}

-End-

发布于 2024-09-04 17:09:00
收藏
分享
海报
0 条评论
49
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~