《C++程序设计第12章 模板.ppt》由会员分享,可在线阅读,更多相关《C++程序设计第12章 模板.ppt(26页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第12章 模板本讲内容提要函数模板 l函数模板l模板函数l模板实参的省略 类模板 l类模板的概念与定义l模板类l类模板的继承与派生 请看下面的函数:void add(int a,int b,int size)for(int i=0;isize;i+)bi+=ai;void add(float a,float b,float size)for(int i=0;isize;i+)bi+=ai;void add(double a,float b,double size)for(int i=0;isize;i+)bi+=ai;如果不限定数组的类型为整型,则一、函数模板函数模板是通过对参数类型进行参数化
2、后,获取有相同形式的函数体。它是一个通用函数,它可适应一定范围内的不同类型对象的操作。函数模板将代表着不同类型的一组函数,它们都使用相同的代码,这样可以实现代码重用,避免重复劳动,又可增强程序的安全性。1.函数模板利用函数模板解决上述问题。函数模板的定义格式:template ()参数化类型名表又称模板参数表,多个表项用逗号分隔。每个表项称为一个模板参数(模板形参)。格式如下:class 或typename或 add模板可以定义为:其中,“”括起部分就是模板的形参表,T是一个虚拟类型参数。注意,可以用多个虚拟参数构成模板形参表。不但普通函数可以声明为函数模板,类的成员函数也可以声明为函数模板。
3、template void add(T a,T b,int size)for(int i=0;isize;i+)bi+=ai;2.模板函数 函数模板是模板函数的一个样板,它可以生成多个重载的模板函数,这些模板函数重用函数体代码。模板函数是函数模板的一个实例。函数模板的实例化(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;isize;i+)bi+=ai;template void add(T1 a,T2 b,int
4、 size)for(int i=0;isize;i+)bi+=ai;例12.1:问题:分析程序输出结果。template void bubble(stype*item,int count)stype bubb;for(int i=0;i=count-1;i+)for(int j=i+1;jitemj)bubb=itemi;itemi=itemj;itemj=bubb;#include#includetemplate void bubble(stype*item,int count);void main()int nums1=4,7,2,9,3,7,6,1;bubble(nums1,8);cou
5、tThe sorted numbers are;for(int i(0);i8;i+)coutnums1i;coutendl;double nums2=2.3,5.3,6.7,3.9,7.2,1.5;bubble(nums2,6);coutThe sorted numbers are;for(i=0;i6;i+)coutnums2i;coutendl;3.模板实参的省略 模板实参的省略是有条件的。以下四种情况模板实参不能省略:l从模板函数实参表获得的信息有矛盾。l需要获得特定类型的返回值,而不管参数的类型如何。l虚拟类型参数没有出现在模板函数的形参表中。l函数模板含有常规形参。从模板函数实参表
6、获得的信息有矛盾。例如:ltemplatelT add(T a,T b)return a+b;若调用函数的语句为:coutadd(3,5);l则编译系统无论是从3还是5所获得的信息都是T对应于int,因此可顺利地生成如下模板函数:int add(int a,int b)return a+b;调用语句变为:lcoutadd(3.0,5);l其中,紧跟在函数名后的就是模板实参表,此时,编译系统生成如下的模板函数:int add(int a,int b)return a+b;需要获得特定类型的返回值,而不管参数的类型如何。例如,l如果需要add返回一个int型的值,l那么直接以add(a,b);形式
7、调用即可。虚拟类型参数没有出现在模板函数的形参表中。由于虚拟类型参数没有出现在模板函数的形参表中,所以调用时不可能从模板函数的实参表中获得相应的信息,因此无法省略。例12.2 分析程序输出结果。#includeusing namespace std;templateT2 add(T1 a,T3 b)return a+b;void main()coutshowpoint;coutadd(3,5L)endl;coutadd(3,5L)endl;程序运行结果为:程序运行结果为:88.00000函数模板含有常规形参。当函数模板含有常规形参时,如果常规参数的信息无法从模板函数的实参表中获得,则在调用时必
8、须显式的给出对应于常规参数的模板实参。例12.3 分析程序输出结果。#includeusing namespace std;template sum(T data,T&result)result=0;for(int i=0;irows;i+)result+=datai;int main()int d3=1,2,3;int r;/此处必须显式给出对应于常规参数的模板实参此处必须显式给出对应于常规参数的模板实参 sum(d,r);coutsum=rendl;return 0;程序运行结果为:程序运行结果为:sum=6二、类模板1.为何要引进类模板?l按不同的方式重用相同的代码l使代码参数化(通用化
9、),即不受类型和操作的影响使用类模板所定义的一种类类型,类中的某些数据成员和某些成员函数的参数及返回值可以选取一定范围内的多种类型,从而实现代码重用。是一种参数化类型的类,是类的生成器。讨论引进类模板的必要性有如下程序:Node是链表的节点类,List为链表类。class Node;class Listpublic:List();List();void Add(Node&);void Remove(Node&);Node*Find(Node&);/该类的实现部分略通用化修改,使用参数Tclass Listpublic:List();List();void Add(T&);void Remove
10、(T&);Node*Find(T&);/该类的实现部分略2.类模板(1)类模板的定义templateclass;/类体实现模板参数表lclass 例如,array.h文件中类模板的定义(2)用类模板定义对象的格式是:();3.模板类模板类在定义了类模板后,可根据需要生成相应的模板类。即,对模板参数,指定具体的类型。l例如,当指定AType 为int型时,生成模板类 array 利用模板类创建对象格式如下:larray a1=10;例12.4:问题:分析程序输出结果。#include#includetemplate class stackpublic:stack(int size);stack(
11、)delete stck;void push(T i);T pop();private:int tos,length;T*stck;程序运行结果为:程序运行结果为:9 8 7 6 5 4 3 2 1 022.5 20 17.5 15 12.5 10 7.5 5 2.5 0a b c d e f g h i jtemplatestack:stack(int size)/构造函数构造函数stck=new Tsize;if(!stck)coutcannot allocate stack.n;exit(1);length=size;/栈长度栈长度tos=0;template void stack:pu
12、sh(T i)/入栈入栈if(tos=length)/满栈满栈coutStack is full.n;stcktos=i;tos+;template T stack:pop()/出栈出栈if(tos=0)coutStack underflow.n;tos-;return stcktos;void main()stack a(10);/模板类模板类stackstack b(10);/模板类模板类stackstack c(10);/模板类模板类stackfor(int i=0;i10;i+)a.push(i);for(i=0;i10;i+)b.push(i*2.5);for(i=0;i10;i+)
13、couta.pop();coutendl;for(i=0;i10;i+)coutb.pop();coutendl;for(i=0;i10;i+)c.push(char)j-i);for(i=0;i10;i+)coutc.pop();coutendl;4.类模板的继承与派生 模板类的派生与普通类一样,也分为公有派生类、保护派生类和私有派生类三种。模板派生类中成员的访问控制规则与普通类也是一样的。下面给出常见的几种情况:l普通类继承类模板 l模板类继承普通类l模板类继承模板类 l模板类继承模板参数给出的基类 普通类继承类模板可以通过继承类模板的一个实例来声明一个类,例如:templateclass
14、 TBaseT data;class Derived:public TBase;模板类继承普通类模板类TDerived继承了普通类TBase,这种情况十分常见。例如:class TBase;templateclass TDerived:public TBaseT data;模板类继承模板类例如:templateclass TBaseT data1;templateclass TDerived:public TBaseT2 data2;模板类继承模板参数给出的基类继承哪个基类由模板参数决定。例12.5 分析程序输出结果。#includeusing namespace std;class Base
15、Apublic:BaseA()coutBaseA founedendl;class BaseBpublic:BaseB()coutBaseB founedendl;templateclass BaseCprivate:T data;public:BaseC(T n=value):data(n)coutBaseC founed dataendl;templateclass Derived:public Tpublic:Derived():T()coutDerived founedendl;void main()Derived x;/BaseA作为基类作为基类Derived y;/BaseB作为基类作为基类DerivedBaseC z;/BaseC作为基类作为基类程序运行结果为:程序运行结果为:BaseA founedDerived founedBaseB founedDerived founedBaseC founed 3Derived founed类模板和模板类小结类模板是一个类型参数化的样板,它是一组模板类的集合。模板类是某个类模板的实例。使用某个具体的类型来替换某个类模板的模板参数可以生产该类模板的一个模板类。可以通过模板类再创建具体的对象。类模板的作用:让类参数化,以加强其通用性,提供代码的重用率。练习与作业
限制150内