CC++作为强类型语言,变量和函数参数、返回值是一定要声明类型的,对于某些算法来说,除了数据类型不同以外,其它代码(逻辑)都是一样的。
我们希望能够将这些通用性较强的算法做成模板(Template),只需要填入相应的数据类型,就能立刻可用。
C++中的模板分为两种:函数模板和类模板,分别适用于面向过程和面向对象的程序设计。
1 函数模板
函数模板是一系列相关函数的模型或样板,这些函数的源代码形式相同,只是所针对的数据类型不同。对于函数模板,数据类型本身成了它的参数,因而是一种参数化类型的函数。
函数模板与普通函数相似,也有函数模板原型、函数模板头、函数模板体。
函数模板的原型为:
template 返回值类型 函数名(参数表); 例如: template 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 Buffer;
类模板通常应用于对各种数据类型适用的数据存储类。例如链表类、向量(数组)类、栈类等。
通过使用链表类模板,可以创建出存储整型的链表、存储字符的链表以及存储字符串的链表。
类模板的定义与类的定义相似,但在某些合适的地方将具体的数据类型改为数据类型参数。例如:
对于在类模板定义内定义的成员函数,与一般的成员函数在类定义内的定义方式一致。
对于在类模板定义外定义的成员函数,格式为:
template 返回值类型 模板名::成员函数名(参数表) { 语句1; 语句2; …… }
在使用类模板时,先要填入对应的数据类型参数c++模板类,使其变成一个完整的类,然后再用这个类来创建一个对象。因此,用类模板创建一个对象的方法为:
类模板名 对象名(初始化数据);
实例代码:
运行效果:
请输入一个整数: 4 Node constructor is running... Linklist constructor is running... Node constructor is running... Node constructor is running... After Linklista Insert 4 2 1 请输入一个字符: e Node constructor is running... Linklist constructor is running... Node constructor is running... Node constructor is running... After Linklist b Insert e P C
附代码1:
#include using namespace std; template 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 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]!='';i++) temp[i]=a[i]; //所有a数组元素复制到temp数组 temp[i]=''; //填补结尾符 for (i=0;b[i]!='';i++) a[i]=b[i]; //所有b数组元素复制到a数组 a[i]=''; for (i=0;temp[i]!='';i++) b[i]=temp[i]; //所有temp数组元素复制到b数组 b[i]=''; return; }
附代码2:
#include #include using namespace std; template T smaller( T a, T b ) /* 函数模板 */ { if ( a <= b ) { return(a); }else { return(b); } } char * smaller( char *a, char *b ) /* 重载函数 */ { if ( strlen( a ) <= strlen( b ) ) /* strlen函数返回字符串的长度 */ { return(a); }else { return(b); } } int main() { cout << smaller( 8, 22 ) << endl; cout << smaller( 99.88, 2.65 ) << endl; cout << smaller( "Tomato Studio", "Shanghai University" ) << endl; cout << smaller( "Tomato", "tomato" ) << endl; system( "pause" ); return(0); }
附代码3:
//3个文件
//main.cpp
//linklist.h
//node.h
//main.cpp
#include “linklist.h”
#include
using namespace std;
int main()
{
int tempi;
char tempc;
cout next=pcurrent->next; //先连
pcurrent=temp->prior;
delete temp; //后断
return true;
}
else
{
return false;
}
}
template void Linklist::Show()
{
Node * ptemp=&head;
while (ptemp!=NULL) //链表的遍历
{
cout <
data next;
}
}
template void Linklist::Destroy()
{
Node * ptemp1=head.next;
while (ptemp1!=NULL) //逐一删除结点对象
{
Node * ptemp2=ptemp1->next;
delete ptemp1;
ptemp1=ptemp2;
}
head.next=NULL;
}
//node.h
#include
using namespace std;
template class Linklist;
//如果要将一个类模板作为友元,必须声明它的存在
template class Node //定义一个链表结点类模板
{
friend class Linklist; //链表类模板作为友元
public:
Node();
Node(Node &n); //参数是一个模板类对象的引用c++模板类,不可缺少
Node(T a); //构造函数重载1
Node(T a,Node *p,Node *n); //构造函数重载2
~Node();
private:
T data; //成员数据的类型由类型参数T决定
Node *prior;
Node *next;
};
template Node::Node()
{
cout
限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688