第20章 模板
20.1 模板的概念
1.若两个或两个以上函数的程序部分完全相同,差别近在于它们的参数不同。如:
int max(int x,int y){return(x>y)?x:y;}
float max(float x,float y){return(x>y)?x:y;}
则可将这些结构相同的函数归结为一个抽象的函数,称之为函数模板(function template)。
由函数模板经实例化而生成的具体函数称之为模板函数。
2.若两个类或多个类的结构部分完全相同,差别仅在于数据类型不同,也可将这些结构相同的类归结为一个抽象的类,称之为类模板(class template)。
由类模板经实例化而生成的具体类称之为模板类。
20.2 函数模板和模板函数
1.函数模板定义和模板函数生成。
定义格式:template<class type>
type<函数名>(type<形参1>,…, type<形参n>)
{<函数体>}
其中:type为类型参数。
函数模板定义后,在程序中可直接调用,调用后编译将生成具体的模板函数。
例20.1 如何定义函数模板
template<class T>
T max(T x,T y)
{return (x>y)?x:y;}
#include<iostream.h>
void main()
{
int i=5,j=10;
float x1=12.3,x2=21.4;
double y1=555.66,y2=888.99;
cout<<"max("<<i<<","<<j<<")"<<max(i,j)<<endl;
cout<<"max("<<x1<<","<<x2<<")"<<max(x1,x2)<<endl;
cout<<"max("<<y1<<","<<y2<<")"<<max(y1,y2)<<endl;
}
2.重载函数模板
例20.2如何重载函数模板
template<class Type>
Type max(Type x,Type y)
{return (x>y)?x:y;}
template<class Type>
Type max(Type x,Type y,Type z)
{Type t;
t=(x>y)?x:y;
return (t>z)?t:z;}
#include<iostream.h>
void main()
{
int m=10,n=20,max2;
float a=10.1,b=20.2,c=30.3,max3;
max2=max(m,n);
max3=max(a,b,c);
cout<<"max("<<m<<","<<n<<")="<<max2<<endl;
cout<<"max("<<a<<","<<b<<","<<c<<")="<<max3<<endl;
}
结果:max(10,20)=20
max(10.1,20.2,30.3)=30.3
3.重载模板函数
例20.3 如何重载模板函数
#include<iostream.h>
#include<string.h>
template<class T>
T max(T a,T b)
{return (a>b)?a:b;}
char* max(char* a,char* b)
{return (strcmp(a,b)?a:b);}
void main()
{
cout<<"Max(\"Hello\",\"Gold\")is"
<<max("Hello","Gold")<<endl;
}
结果:Max("Hello","Gold") is Hello
该例中,调用的是非模板函数char* max(char*,char*)
4.C++中函数调用的一般顺序为:
(1)寻找一个参数完全匹配的函数,若找到则调用之,否则
(2)寻找一个函数模板,若找到则将其实例化为一个模板函数,然后调用之,否则
(3)寻找重载函数,考察有无可通过类型转换产生参数匹配的函数,若有则调用之。
20.3 类模板和模板类
1.类模板定义和模板类生成
定义格式:template<class type>
class<类名>{
type<数据成员1>;
type<数据成员2>;
…
type<数据成员n>;
//其他数据成员
…
};
例:template<class T>
class Vector{
T* data;
int size
public:
Vector(int);
T& operator[](int);
…
};
2.若模板类的成员函数在类外定义时,若此函数中含有模板参数,则需在函数名前的类名后加上"<type>",同时,在前面应写上模板声明(template<class 模板形参表>)。
例:template<class T>
Vector<T>::Vector(int)
{…}
T& Vector<T>::operator[](int)
{…}
3.用类模板生成模板类的格式
类名<具体类型>
或
类名<具体类型> 对象名[(实参表)];
例:Vector<int> x(10);
//生成int型的模板类Vector,并产生对象x。
例:堆栈类模板
template<class T>
class stack{
T* data;
int top;
int size;
int IsEmpty(){return (top<0)?1:0;}
int IsFull(){return (top==size)?1:0;}
public:
stack(int n)
{ data=new T[n];
size=n;
top=0;
}
~stack(){delete []data;}
void pop(T a);
T push();
};
4.举例
例20.4 定义一个单向链表的模板类,分别实现增加、删除、寻找和打印操作。
//listtmp.h
#include<iostream.h>
template<class T>
class list
{public:
list();
void add(T&);
void remove(T&);
T* find(T&);
void printlist();
~list();
protected:
struct node
{ node* pnext;
T* pt;
};
node* pfirst;
};
template<class T>
list<T>::list()
{pfirst=0;}
template<class T>
void list<T>::add(T& t)
{ node* temp=new node;
temp->pt=&t;
temp->pnext=pfirst;
pfirst=temp;
}
template<class T>
void list<T>::remove<T& t>
{node* q=0;
if(*(pfirst->pt)==t)
{q=pfirst;
pfirst=pfirst->pnext;
}
else
{for(node* p=pfirst;p->pnext;p=p->pnext)
if(*(p->pnext->pt)==t)
{q=p->pnext;
p->pnext=q->pnext;
break;
}
}
if(q){
delete q->pt;
delete q;
}
}
template<class T>
T* list<T>::find(T& t)
{for(node* p=pfirst;p;p->next)
{if(*(p->pt)==t)
return p->pt;
}
return 0;
}
template<class T>
void list<T>::printlist()
{for(node* p=pfirst;p;p->next)
{cout<<*(p->pt)<<" ";
}
cout<<endl;
}
template<class T>
list<T>::~list()
{node* p;
while(p=pfirst)
{pfirst=pfirst->pnext;
delete p->pt;
delete p;
}
}
//ch204.cpp
#include"listtmp.h"
void main()
{list<float> floatlist;
for(int i=1;i<7;i++)
{floatlist.add(* new float(i+0.6));
}
floatlist.printlist();
float b=3.6;
float *pa=floatlist.find(b);
if(pa)
floatlist.remove(*pa);
floatlist.printlist();
}
结果:6.6 5.6 4.6 3.6 2.6 1.6
6.6 5.6 4.6 2.6 1.6
20.1 模板的概念
1.若两个或两个以上函数的程序部分完全相同,差别近在于它们的参数不同。如:
int max(int x,int y){return(x>y)?x:y;}
float max(float x,float y){return(x>y)?x:y;}
则可将这些结构相同的函数归结为一个抽象的函数,称之为函数模板(function template)。
由函数模板经实例化而生成的具体函数称之为模板函数。
2.若两个类或多个类的结构部分完全相同,差别仅在于数据类型不同,也可将这些结构相同的类归结为一个抽象的类,称之为类模板(class template)。
由类模板经实例化而生成的具体类称之为模板类。
20.2 函数模板和模板函数
1.函数模板定义和模板函数生成。
定义格式:template<class type>
type<函数名>(type<形参1>,…, type<形参n>)
{<函数体>}
其中:type为类型参数。
函数模板定义后,在程序中可直接调用,调用后编译将生成具体的模板函数。
例20.1 如何定义函数模板
template<class T>
T max(T x,T y)
{return (x>y)?x:y;}
#include<iostream.h>
void main()
{
int i=5,j=10;
float x1=12.3,x2=21.4;
double y1=555.66,y2=888.99;
cout<<"max("<<i<<","<<j<<")"<<max(i,j)<<endl;
cout<<"max("<<x1<<","<<x2<<")"<<max(x1,x2)<<endl;
cout<<"max("<<y1<<","<<y2<<")"<<max(y1,y2)<<endl;
}
2.重载函数模板
例20.2如何重载函数模板
template<class Type>
Type max(Type x,Type y)
{return (x>y)?x:y;}
template<class Type>
Type max(Type x,Type y,Type z)
{Type t;
t=(x>y)?x:y;
return (t>z)?t:z;}
#include<iostream.h>
void main()
{
int m=10,n=20,max2;
float a=10.1,b=20.2,c=30.3,max3;
max2=max(m,n);
max3=max(a,b,c);
cout<<"max("<<m<<","<<n<<")="<<max2<<endl;
cout<<"max("<<a<<","<<b<<","<<c<<")="<<max3<<endl;
}
结果:max(10,20)=20
max(10.1,20.2,30.3)=30.3
3.重载模板函数
例20.3 如何重载模板函数
#include<iostream.h>
#include<string.h>
template<class T>
T max(T a,T b)
{return (a>b)?a:b;}
char* max(char* a,char* b)
{return (strcmp(a,b)?a:b);}
void main()
{
cout<<"Max(\"Hello\",\"Gold\")is"
<<max("Hello","Gold")<<endl;
}
结果:Max("Hello","Gold") is Hello
该例中,调用的是非模板函数char* max(char*,char*)
4.C++中函数调用的一般顺序为:
(1)寻找一个参数完全匹配的函数,若找到则调用之,否则
(2)寻找一个函数模板,若找到则将其实例化为一个模板函数,然后调用之,否则
(3)寻找重载函数,考察有无可通过类型转换产生参数匹配的函数,若有则调用之。
20.3 类模板和模板类
1.类模板定义和模板类生成
定义格式:template<class type>
class<类名>{
type<数据成员1>;
type<数据成员2>;
…
type<数据成员n>;
//其他数据成员
…
};
例:template<class T>
class Vector{
T* data;
int size
public:
Vector(int);
T& operator[](int);
…
};
2.若模板类的成员函数在类外定义时,若此函数中含有模板参数,则需在函数名前的类名后加上"<type>",同时,在前面应写上模板声明(template<class 模板形参表>)。
例:template<class T>
Vector<T>::Vector(int)
{…}
T& Vector<T>::operator[](int)
{…}
3.用类模板生成模板类的格式
类名<具体类型>
或
类名<具体类型> 对象名[(实参表)];
例:Vector<int> x(10);
//生成int型的模板类Vector,并产生对象x。
例:堆栈类模板
template<class T>
class stack{
T* data;
int top;
int size;
int IsEmpty(){return (top<0)?1:0;}
int IsFull(){return (top==size)?1:0;}
public:
stack(int n)
{ data=new T[n];
size=n;
top=0;
}
~stack(){delete []data;}
void pop(T a);
T push();
};
4.举例
例20.4 定义一个单向链表的模板类,分别实现增加、删除、寻找和打印操作。
//listtmp.h
#include<iostream.h>
template<class T>
class list
{public:
list();
void add(T&);
void remove(T&);
T* find(T&);
void printlist();
~list();
protected:
struct node
{ node* pnext;
T* pt;
};
node* pfirst;
};
template<class T>
list<T>::list()
{pfirst=0;}
template<class T>
void list<T>::add(T& t)
{ node* temp=new node;
temp->pt=&t;
temp->pnext=pfirst;
pfirst=temp;
}
template<class T>
void list<T>::remove<T& t>
{node* q=0;
if(*(pfirst->pt)==t)
{q=pfirst;
pfirst=pfirst->pnext;
}
else
{for(node* p=pfirst;p->pnext;p=p->pnext)
if(*(p->pnext->pt)==t)
{q=p->pnext;
p->pnext=q->pnext;
break;
}
}
if(q){
delete q->pt;
delete q;
}
}
template<class T>
T* list<T>::find(T& t)
{for(node* p=pfirst;p;p->next)
{if(*(p->pt)==t)
return p->pt;
}
return 0;
}
template<class T>
void list<T>::printlist()
{for(node* p=pfirst;p;p->next)
{cout<<*(p->pt)<<" ";
}
cout<<endl;
}
template<class T>
list<T>::~list()
{node* p;
while(p=pfirst)
{pfirst=pfirst->pnext;
delete p->pt;
delete p;
}
}
//ch204.cpp
#include"listtmp.h"
void main()
{list<float> floatlist;
for(int i=1;i<7;i++)
{floatlist.add(* new float(i+0.6));
}
floatlist.printlist();
float b=3.6;
float *pa=floatlist.find(b);
if(pa)
floatlist.remove(*pa);
floatlist.printlist();
}
结果:6.6 5.6 4.6 3.6 2.6 1.6
6.6 5.6 4.6 2.6 1.6
回复Comments
作者:
{commentrecontent}