资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,面向对象程序设计教程,第,3,章 模板,3.1,模板的概念,模板,使用,模板,可以建立具有,通用类型的函数库,或,类库,,为一系列逻辑功能相同而数据类型不同的,函数,或,类创建框架,模板,提供了一种重用,程序源代码,的有效方法,方便了大规模的软件开发,模板的概念,模板,的本质就是将所处理的,数据类型说明为参数,,模板是对具有相同特性的,函数,或,类,的,再抽象,,将程序所处理的数据的,类型参数化,,这样可使,一段程序代码,能用于处理多种,不同类型的数据,。,C+,程序由,类,和,函数,组成,,类,对应,类模板,,,函数,对应,函数模板,。,引入函数模板,考察三个,Swap(),函数,分别用于交换两个,整型数,、交换两个,浮点实型数,以及交换两个,双精度实型数,这三个,Swap(),函数的功能完全一样,只有所处理的数据的类型不同,void Swap(int&x,int&y)/,交换整型数,x,y,int temp=x;x=y;y=temp;/,通过循环赋值交换,x,y,void Swap(float&x,float&y)/,交换浮点实型数,x,y,float temp=x;x=y;y=temp;/,通过循环赋值交换,x,y,void Swap(double&x,double&y)/,交换双精度实型数,x,y,double temp=x;x=y;y=temp;/,通过循环赋值交换,x,y,上面通过,函数重载,实现了让,函数,Swap(),处理,不同类型的数据,,要求交换任何一对,同一种类型,的数据。最好的解决方法是,类型参数化,,这样就得到了,函数模板,。使用函数模板定义如下:,template/class,不是类标识,只表明,ElemType,是类型参数,void Swap(ElemType&x,ElemType&y)/,交换,x,y,ElemType temp=x;x=y;y=temp;/,通过循环赋值交换,x,y,这样得到可以将,任一类型,ElemType,的两个数据进行,互换,的,函数模板,。,引入类模板,三个类,Integer,、,Float,和,Double,分别用来处理,整型数,、,浮点型实数,以及,双精度实型数,这三种类的处理功能完全一样,只有所处理的数据的类型不同,/,声明整型类,class Integer,private:,/,数据成员,int num;/,数据值,public:,/,公有函数,Integer(int n=0):num(n)/,构造函数,void Set(int n)num=n;/,设置数据值,int Get()const return num;/,返回数据值,;,/,声明浮点型实数类,class Float,private:,/,数据成员,float num;/,数据值,public:,/,公有函数,Float(float n=0):num(n)/,构造函数,void Set(float n)num=n;/,设置数据值,float Get()const return num;/,返回数据值,;,/,声明双精度实型数类,class Double,private:,/,数据成员,double num;/,数据值,public:,/,公有函数,Double(double n=0):num(n)/,构造函数,void Set(double n)num=n;/,设置数据值,double Get()const return num;/,返回数据值,;,上面实现的三个类的功能相同,处理,不同类型的数据,,采用类型参数化后就可以,处理任何类型,,这样就得到了,类模板,。使用类模板定义如下:,template,class Number,private:,/,数据成员,ElemType num;/,数据值,public:,/,公有函数,Number(ElemType n=0):num(n)/,构造函数,void Set(ElemType n)num=n;/,设置数据值,ElemType Get()const return num;/,返回数据值,;,函数模板,或,类模板,是对,一族函数或类的描述,,,模板是,使用,类型参数,来产生,一组函数,或,类,的机制。,3.2,函数模板及模板函数,3.2.1,函数模板及模板函数,函数模板,是对一批功能相同的函数的说明,它不是某一个具体的函数,是带有“,类型参数,”的一种描述,模板函数,是将函数模板内的“,数据类型参数,”取某一个具体的数据类型后得到的,具体函数,函数模板的声明,使用函数模板的方法是先声明函数模板,最后才可以调用模板函数。函数模板的一般声明格式如下:,template,返回值类型 函数模板名,(,形参表,),/,函数模板体,或,template,返回值类型 函数模板名,(,形参表,),/,函数模板体,template,是一个声明模板的关键字,class,在此处并不表示类的意思,只是借用此关键字表示其后是一个类型参数。,class,类型参数名,1,class,类型参数名,2,称为类型形参表,class,和,typename,的作用相同,都是表示“类型名”,二者可以互换,生成模板函数,在使用函数模板时,用实际的,数据类型,具体化(实例化),类型形式参数,,再根据,实际参数类型,,生成一个具体的,模板函数,,,模板函数,的,函数体,与,函数模板,的,函数模板体,完全相同,在程序中真正执行的代码是模板函数的代码,在使用函数模板生成模板函数时,有两种使用方式:,函数模板名,(,实参表,),或,函数模板名,(,实参表,),第一种使用方式将根据,实参类型,确定,类型形式参数,的,具体类型,,第二种方式中,,称为,类型实参表,,用,类型实参表,中的,类型,来确定,类型形式参数具体类型,只有一个类型形参的函数模板,类型形参表与类型实参表通常只包含一个类型,这时函数模板的一般声明格式如下:,template,返回值类型 函数模板名,(,形参表,),/,函数模板体,或,template,返回值类型 函数模板名,(,形参表,),/,函数模板体,使用函数模板生成模板函数的两种使用方式如下:,函数模板名,(,实参表,),或,函数模板名,(,实参表,),例,3.1,函数模板定义与模板函数的调用示例。,template,ElemType Max(ElemType x,ElemType y)/,求,x,y,的最大值,return x y?y:x;/,返回,x,y,的最大值,int main()/,主函数,main(),cout 2,和,3,的最大值为,Max(2,3)endl;/,输出,2,3,的最大值,/cout 2,和,3.0,的最大值为,Max(2,3.0)endl;,/,错,无法根据,2,3.0,确定类型形式参数的具体类型,cout 2,和,3.0,的最大值为,(2,3.0)endl;,/,输出,2,3.0,的最大值,system(PAUSE);/,调用库函数,system(),,输出系统提示信息,return 0;/,返回值,0,返回操作系统,程序运行时屏幕输出如下:,2,和,3,的最大值为,3,2,和,3.0,的最大值为,3,请按任意键继续,.,3.2.2,重载函数模板,模板函数,类似于,重载函数,,但是同一个函数模板类型形式参数具体化(实例化)后的所有模板函数必须,执行相同的代码,,而,函数重载,时在每个函数体中可以,执行不同的代码,,当遇到执行的代码有所不同时,不能简单地套用函数模板,而应像,重载普通函数那样进行重载,重载函数模板,后,编译器首先,匹配类型完全相同的函数,,如果匹配失败,再寻求,函数模板,进行,匹配,例,3.2,重载函数模板与匹配过程示例。,template,ElemType Max(ElemType x,ElemType y)/,求,x,y,的最大值,return x y?y:x;/,返回,x,y,的最大值,char*Max(char*str1,char*str2)/,求,str1,str2,的最大值,return strcmp(str1,str2)0?str2:str1;/,返回,str1,str2,的最大值,int main()/,主函数,main(),cout 2,和,3,的最大值为,Max(2,3)endl;,/,输出,2,3,的最大值,匹配,函数模板,cout China,与,American,的最大值为,Max(China,American)endl;,/,输出,China,American,的最大值,匹配函数,system(PAUSE);/,输出系统提示信息,return 0;/,返回值,0,返回操作系统,程序运行时屏幕输出如下:,2,和,3,的最大值为,3,China,与,American,的最大值为,China,请按任意键继续,.,例,3.3,重载函数模板示例。,template,ElemType Max(ElemType x,ElemType y)/,求,x,y,的最大值,return x y?y:x;/,返回,x,y,的最大值,template,ElemType Max(ElemType x,ElemType y,ElemType z)/,求,x,y,z,的最大值,ElemType m=x y?y:x;/m,为,x,y,的最大值,m=m z?z:m;/m,z,的最大值,return m;/,返回最大值,template,ElemType Max(ElemType a,int n)/,求,a0,a1,.,an-1,的最大值,ElemType m=a0;/,假设,a0,为最大值,for(int i=1;i n;i+),if(m ai)m=ai;/,如,ai,更大,则将,ai,赋值给,m,return m;/,返回最大值,int main()/,主函数,main(),int a=1,9,7,5,6,3;/,定义数组,a,cout ,数组,a,的最大元素值为,Max(a,6)endl;,cout 2,和,3,的最大值为,Max(2,3)endl;,cout 2,3,和,8,的最大值为,Max(2,3,8)endl;,system(PAUSE);/,输出系统提示信息,return 0;/,返回值,0,返回操作系统,程序运行时屏幕输出如下:,数组,a,的最大元素值为,9,2,和,3,的最大值为,3,2,3,和,8,的最大值为,8,请按任意键继续,.,3.3,类模板及模板类,类模板及模板类,类模板,与,函数模板,类似,它可以为,任意数据类型,定义一种,模板,,使用不同的,数据类型,具体化(实例化),类模板,生成具体的,模板类,模板类,可以用于生成具体的,对象,3.3.1,类模板的声明及生成模板类,定义一个类模板与定义函数模板的格式类似,必须以关键字,template,开始,类模板的一般声明形式如下:,template,class,类模板名,/,类模板体,;,或,template,class,类模板名,/,类模板体,;,类模板的声明,类模板,的成员函数不但可以在,类模板内定义,,也可以在,类模板外定义,。在类模板外定义时,需要采用下面的形式:,template,返回值类型 类模板名,:,成员函数名,(,形参表,),/,函数体,或,template,返回值类型 类模板名,:,成员函数名,(,形参表,),/,函数体,生成模板类,类模板,必须用实际的,数据类型,具体化(实例化),类型形式参数,,再根据实际参数类型,生成一个具体的,模板类,,然后才能用来生成具体对象。,一般语法格式如下:,类模板名,对象名,;,例,3.4,使用类模板的实例。,/,声明数组类模板,template,class Array,private:,/,数据成员,ElemType*elem;/,存储数据元素值,int size;/,数组元素个数,public:,/,公有函数,Array(int sz):size(sz)elem=new ElemTypesize;/,构造函数,Array()delete elem;/,析构函数,void SetElem(ElemType e,int i);/,设置元素值,ElemType GetElem(int i)const;/,求元素值,;,例,3.4,使用类模板的实例。,template,void Array:SetElem(ElemType e,int i)/,设置元素值,if(i=size),cout ,元素位置错,!endl;,exit(1);/,退出程序的运行,返回到操作系统,elemi=e;/,设置元素值为,e,template,ElemType Array:GetElem(int i)const/,求元素值,if(i=size),cout ,元素位置错,!endl;,exit(2);/,退出程序的运行,返回到操作系统,return elemi;/,返回元素值,elemi,例,3.4,使用类模板的实例。,int main()/,主函数,main(),int a=1,9,7,5,6,3;/,定义数组,a,int n=6;/,数组元素个数,Array obj(n);/,定义数组对象,int i;/,定义临时变量,for(i=0;i n;i+),obj.SetElem(ai,i);/,设置数组元素值,for(i=0;i n;i+),cout obj.GetElem(i);/,输出元素值,cout endl;/,换行,system(PAUSE);/,输出系统提示信息,return 0;/,返回值,0,返回操作系统,程序运行时屏幕输出如下:,1 9 7 5 6 3,请按任意键继续,.,3.3.2,在类型形参表中包含常规参数的类模板,在声明类模板的,类型形参表,中还可以包含,常规参数,,常规参数经常是数值。,对模板类进行具体化,(,实例化,),为模板类时给这些,常规参数,所提供的表达式必须是,常量表达式,。,例,3.5,使用在类型形参表中包含常规参数的实例。,/,声明数组类模板,template,class Array,private:,/,数据成员,ElemType elemsize;/,存储数据元素值,public:,/,公有函数,void SetElem(ElemType e,int i);/,设置元素值,ElemType GetElem(int i)const;/,求元素值,;,常规参数,例,3.5,使用在类型形参表中包含常规参数的实例。,template,void Array:SetElem(ElemType e,int i)/,设置元素值,if(i=size),cout ,元素位置错,!endl;,exit(1);/,退出程序的运行,返回到操作系统,elemi=e;/,设置元素值为,e,template,ElemType Array:GetElem(int i)const/,求元素值,if(i=size),cout ,元素位置错,!endl;,exit(2);/,退出程序的运行,返回到操作系统,return elemi;/,返回元素值,elemi,例,3.5,使用在类型形参表中包含常规参数的实例。,int main()/,主函数,main(),int a=1,9,7,5,6,3;/,定义数组,a,const int n=6;/,数组元素个数,Array obj;/,定义数组对象,int i;/,定义临时变量,for(i=0;i n;i+),obj.SetElem(ai,i);/,设置数组元素值,for(i=0;i n;i+),cout obj.GetElem(i);/,输出元素值,cout endl;/,换行,system(PAUSE);/,输出系统提示信息,return 0;/,返回值,0,返回操作系统,程序运行时屏幕输出如下:,1 9 7 5 6 3,请按任意键继续,.,
展开阅读全文