C template
Document Sample


第12章 模板
本讲内容提要
函数模板
函数模板
模板函数
模板实参的省略
类模板
类模板的概念与定义
模板类
类模板的继承与派生
请看下面的函数:
void add(int a[],int b[],int size){
for(int i=0;i<size;i++) b[i]+=a[i];
}
如果不限定数组的类型为整型,则……
void add(float a[],float b[],float size){
for(int i=0;i<size;i++) b[i]+=a[i];
}
void add(double a[],float b[],double size){
for(int i=0;i<size;i++) b[i]+=a[i];
}
……
一、函数模板
函数模板是通过对参数类型进行参数化后,
获取有相同形式的函数体。
它是一个通用函数,它可适应一定范围内
的不同类型对象的操作。
函数模板将代表着不同类型的一组函数,
它们都使用相同的代码,这样可以实现代
码重用,避免重复劳动,又可增强程序的
安全性。
1.函数模板
利用函数模板解决上述问题。
函数模板的定义格式:
template <(参数化类型名表)><类型> <函数名>(<模板参数表>)
{
<函数体>
}
参数化类型名表又称模板参数表,多个表项用逗号分隔。
每个表项称为一个模板参数(模板形参)。格式如下:
class <参数名>
或typename<参数名>
或<类型修饰> <参数名>
add模板可以定义为:
template <class T>
void add(T a[],T b[],int size){
for(int i=0;i<size;i++) b[i]+=a[i];
}
其中,“< >”括起部分就是模板的形参表,T是
一个虚拟类型参数。注意,可以用多个虚拟参数
构成模板形参表。
不但普通函数可以声明为函数模板,类的成员函
数也可以声明为函数模板。
2.模板函数
函数模板是模板函数的一个样板,它可以
生成多个重载的模板函数,这些模板函数
重用函数体代码。
template <typename T1,typename T2>
void add(T1 a[],T2 b[],int size){
模板函数是函数模板的一个实例。
for(int i=0;i<size;i++) b[i]+=a[i];
} 函数模板的实例化(instantiation)
long float x[]={1,2,3,4,5,6},y[]={7,8,9,10,11,12};
add(x,y,6);
void add(float a[],float b[],float size){
for(int i=0;i<size;i++) b[i]+=a[i];
}
#include <iostream.h>
例12.1:
#include<string.h>
template<class stype> void bubble(stype *item, int count);
问题:分析程序输出结果。
void main()
{int nums1[]={4,7,2,9,3,7,6,1};
template<class stype>
bubble(nums1,8);
void bubble(stype *item, int count)
cout<<"The sorted numbers are ";
{
for(int i(0);i<8;i++)
stype bubb;
cout<<nums1[i]<<" ";
cout<<endl; for(int i=0;i<=count-1;i++)
for(int j=i+1;j<count;j++)
double nums2[]={2.3,5.3,6.7,3.9,7.2,1.5};
bubble(nums2,6); if(item[i]>item[j])
{
cout<<"The sorted numbers are ";
for(i=0;i<6;i++) bubb=item[i];
item[i]=item[j];
cout<<nums2[i]<<" ";cout<<endl;}
item[j]=bubb;
}
}
3.模板实参的省略
模板实参的省略是有条件的。
以下四种情况模板实参不能省略:
从模板函数实参表获得的信息有矛盾。
需要获得特定类型的返回值,而不管参数的类
型如何。
虚拟类型参数没有出现在模板函数的形参表中。
函数模板含有常规形参。
从模板函数实参表获得的信息有矛盾。
例如:
template<typename T>
T add(T a,T b){return a+b;}
若调用函数的语句为:cout<<add(3,5);
则编译系统无论是从3还是5所获得的信息都是T对应
于int,因此可顺利地生成如下模板函数:int
add(int a, int b){return a+b;}
调用语句变为:
cout<<add<int>(3.0,5);
其中,紧跟在函数名后的<int>就是模板实参表,
此时,编译系统生成如下的模板函数:
int add(int a,int b){return a+b;}
需要获得特定类型的返回值,而不管参
数的类型如何。
例如,
如果需要add返回一个int型的值,
那么直接以add<int>(a,b);形式调用即可。
虚拟类型参数没有出现在模板函数的形
参表中。
由于虚拟类型参数没有出现在模板函数的
形参表中,所以调用时不可能从模板函数
的实参表中获得相应的信息,因此无法省
略。
#include<iostream>
using namespace std;
例12.2 分析程序输出结果。
template<typename T1,typename T2,typename T3>
T2 add(T1 a,T3 b){return a+b;}
void main()
{ 程序运行结果为:
8 cout<<showpoint;
cout<<add<double,int>(3,5L)<<endl;
8.00000
cout<<add<int,double,long>(3,5L)<<endl;
}
函数模板含有常规形参。
当函数模板含有常规形参时,如果常规参
数的信息无法从模板函数的实参表中获得,
#include<iostream>
namespace std;
using则在调用时必须显式的给出对应于常规参
template <class T,int rows>
sum(T数的模板实参。
data[],T &result)
{result=0;
例12.3 分析程序输出结果。
for(int i=0;i<rows;i++)
result+=data[i];}
int main()
{int d[3]={1,2,3};int r;
//此处必须显式给出对应于常规参数的模板实参
程序运行结果为:
sum<int,3>(d,r);
sum=6
cout<<"sum="<<r<<endl;
return 0;}
二、类模板
1.为何要引进类模板?
按不同的方式重用相同的代码
使代码参数化(通用化),即不受类型和操作
的影响
使用类模板所定义的一种类类型,类中的
某些数据成员和某些成员函数的参数及返
回值可以选取一定范围内的多种类型,从
而实现代码重用。
是一种参数化类型的类,是类的生成器。
讨论引进类模板的必要性
有如下程序:Node是链表的节点类,List为链表类。
class Node {……};
class List{
public:List();
~List();
void Add(Node &);
void Remove(Node &);
Node *Find(Node &);
……
};
//该类的实现部分略……
通用化修改,使用参数T
class List{
public:List();
~List();
void Add(T &);
void Remove(T &);
Node *Find(T &);
……
};
//该类的实现部分略……
2.类模板
(1)类模板的定义
template<模板参数表>
class <类名>
{<类体说明>};
//类体实现
模板参数表
class <标识符>
例如,array.h文件中类模板的定义
(2)用类模板定义对象的格式是:
<类名><<模板实参表>><对象名>(<构造函数实参表>);
3. 模板类
模板类
在定义了类模板后,可根据需要生成相应
的模板类。即,对模板参数,指定具体的
类型。
例如,当指定AType 为int型时,生成模板类
array <int>
利用模板类创建对象格式如下:
array <int> a1=10;
程序运行结果为:
9 8 7 6 5 4 3 2 1 0
例12.4:
22.5 20 17.5 15 12.5 10 7.5 5 2.5 0
a b c d e f g h i j
问题:分析程序输出结果。
void main()
#include<iostream.h>
template<class T>
{ stack T>
template <class<int> a(10);//模板类stack<int>
#include<stdlib.h>
stack<T>::stack(int size)//构造函数
template <class T>
stack <double> b(10);//模板类stack<double>
template <class T>
void stack<T>::push(T i)//入栈
{
T stack <T>::pop()//出栈 c(10);//模板类stack<char>
{ class stack <char>
stack
{ stck=new T[size];
for(int i=0;i<10;i++)a.push(i);
public:
{ if(tos==length)//满栈
if(!stck)
for(i=0;i<10;i++) full.\n";
if(tos==0) stack(int isb.push(i*2.5);
cout<<"Stack size);
{for(i=0;i<10;i++) cout<<a.pop()<<' ';
cout<<"Stack underflow.\n";
~stack()
stck[tos]=i;
tos--; cout<<"cannot allocate stack.\n";
cout<<endl;
{delete [] stck;}
tos++;
exit(1);
for(i=0;i<10;i++) cout<<b.pop()<<' ';
return stck[tos];
void push(T i);
}
} }cout<<endl;
T pop();
length=size;//栈长度c.push((char)'j'-i);
for(i=0;i<10;i++)
private:
tos=0; int tos,length;
for(i=0;i<10;i++) cout<<c.pop()<<' ';
} cout<<endl;}
T *stck;};
4.类模板的继承与派生
模板类的派生与普通类一样,也分为公有
派生类、保护派生类和私有派生类三种。
模板派生类中成员的访问控制规则与普通
类也是一样的。
下面给出常见的几种情况:
普通类继承类模板
模板类继承普通类
模板类继承模板类
模板类继承模板参数给出的基类
普通类继承类模板
可以通过继承类模板的一个实例来声明一
个类 ,例如:
template<class T>
class TBase{
T data;
……
};
class Derived:public TBase<int>{
……
};
模板类继承普通类
模板类TDerived继承了普通类TBase,
这种情况十分常见。 例如:
class TBase{
……
};
template<class T>
class TDerived:public TBase{
T data;
……
};
模板类继承模板类
例如:
template<class T>
class TBase{
T data1;
……
};
template<class T1,class T2>
class TDerived:public TBase<T1>{
T2 data2;
……
};
模板类继承模板参数给出的基类
继承哪个基类由模板参数决定。
#include<iostream>
例12.5 分析程序输出结果。
template<typename T,int value>
using namespace std;
class BaseC{
class
void main() BaseA{
{ private:
public:
T data;
BaseA(){cout<<"BaseA founed"<<endl;}
Derived<BaseA> x;// BaseA作为基类
public:
};
Derived<BaseB> y;// BaseB作为基类
BaseC(T n=value):data(n){
class 程序运行结果为:
BaseB{
Derived<BaseC<int,3> > z;
public: cout<<"BaseC founed "<<data<<endl;}
BaseA founed
// BaseC<int,3>作为基类
} }; Derived founed
BaseB(){cout<<"BaseB founed"<<endl;}
BaseB T>
template<class founed
};
class Derived:public T{
Derived founed
public: BaseC founed 3
Derived():T(){cout<<"Derived
Derived founed
founed"<<endl;}};
类模板和模板类小结
类模板是一个类型参数化的样板,它是一
组模板类的集合。
模板类是某个类模板的实例。
使用某个具体的类型来替换某个类模板的
模板参数可以生产该类模板的一个模板类。
可以通过模板类再创建具体的对象。
类模板的作用:让类参数化,以加强其通
用性,提供代码的重用率。
练习与作业
Related docs
Other docs by xhch
Developing_a_Social_Network_Analysis_and_Visualization_Module_for_Repast_Models
Views: 15 | Downloads: 0
IBS_ch_3_developing_transnational_strategies_building_layers_of_competitive_advantage _1_
Views: 0 | Downloads: 0
Get documents about "