您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 钱能C++程序设计教程14
16:15:451C++程序设计教程(第二版)第十四章模板Chapter14Template清华大学出版社钱能16:15:452思考角度C++程序是一些类型和函数,编程就是设计类型和函数,然后按C++的程序结构来组织模板编程世界上万事万物都具有相似性,许多类型和函数尽管处理的数据不同,但其行为也具有相似性,将相似的类型归为类型族以及相似的函数归为函数族的编程,就是模板编程编程方法的侧重点面向对象编程解决类体系中的不同对象行为表现模板编程解决独立类之间的不同对象行为表现多个独立类可以是多个类继承体系,因而,面向对象编程与模板编程是融合的.16:15:453第十四章内容1.函数模板(FunctionTemplate)2.函数模板参数(FunctionTemplateParameter)3.类模板(ClassTemplate)4.实例化与定做(Instantiation&Specialization)5.程序组织(ProgramOrganization)6.模板的多态(TemplatePolymorphism)7.高级编程(AdvancedProgramming)16:15:4541.函数模板(FunctionTemplate)理想的函数重载是针对不同的参数做不同的事.而形如:voidswap(Type&a,Type&b){Typet=a;a=b;b=t;}的重载函数系所定义的行为序列却相同.这种形式的重载意义不大.16:15:455templatetypenameTvoidswap(T&a,T&b){Tt=a;a=b;b=t;}定义函数模板来表示重载函数系:模板形参函数模板名数据形参函数模板定义体16:15:456templatetypenameTvoidswap(T&a,T&b){Tt=a;a=b;b=t;}intfn(){intix=6,iy=7,ia=3,ib=5;swap(ix,iy);//产生函数定义体swap(ia,ib);//不产生函数定义体//...}函数模板用法:以函数模板名作调用的函数名,以数据实参作参数传递16:15:4572.函数模板参数(FunctionTemplateParameter)数据参数是按值的性质匹配的,所以相容类型之间可以转换类型参数是按名字匹配的,更为苛刻templatetypenameTvoidswap(T&a,T&b){Tt=a;a=b;b=t;}intadd(doublea,doubleb){returna+b;}intfn(){intia=3;doubledb=5.0;chars1[]=good,s2[]=better;intx=add(ia,db);//okswap(ia,db);//errorswap(s1,s2);//error}16:15:458数据形参分:引用型参数(提倡用本项)非引用型参数引用型参数分:引用型参数常量引用型参数16:15:459常量引用型形参其数据形参可以是临时对象,所以,通过显式转换可以规定模板的产生形式.但是,不能被隐式转换的数据形参,其显式模板类型指定失效:templatetypenameTTconst&max(Tconst&a,Tconst&b){returnab?b:a;}intmain(){intia=3;doubledb=6.7;db=maxdouble(ia,db);db=max(static_castdouble(ia),db);db=maxdouble(&ia,db);//error}16:15:4510引用型形参其数据形参与数据实参捆绑,故数据实参应为左值表达式:templatetypenameTvoidswap(T&a,T&b){Tt=a;a=b;b=t;}intmain(){intia=3;constintcb=5;swap(ia,7);//error:7不是左值swapint(ia,7);//error:哪怕类型指定也不济swap(cb,7);//error:constint会引起操作错误swapconstint(ia,7);//error:同上}16:15:4511函数模板重载参数有不同的形式(是否引用,是否常量,甚至是否特殊类型),不同形式的参数,其行为不同,这是模板重载的前提.例如:字串比较很特殊,指针比较与对象比较亦不同,则:templatetypenameTTconst&max(Tconst&a,Tconst&b){returnab?b:a;}templatetypenameTT*const&max(T*const&a,T*const&b){return*a*b?b:a;}constchar*const&max(constchar*const&a,constchar*const&b){returnstrcmp(a,b)0?b:a;}intmain(){intia=3,ib=7;char*s1=”hello”,*s2=”hell”;cout*max(&ia,&ib)”\n”;//matchthesecondtemplatecoutmax(s1,s2)”\n”;//matchthemaxfunctioncoutmax(ia,ib)”\n”;//matchthefirsttemplate}16:15:45123.类模板(ClassTemplate)有些类,比如容器类,处理一种类型的对象与处理另一种类型的对象方法一样,但是就因为处理的对象类型不同,而使该类必须重新定义.例如:CatList,DogList,RabbitList等16:15:4513通过模板类定义,可以解决代码冗繁问题:templatetypenameTclassNode{public:Node(constT&d):c(d),next(0),pref(0){}Tc;Node*next,*pref;};16:15:4514又例如下面的模板类定义,含有模板类的成员:templatetypenameTclassList{NodeT*first,*last;public:List();voidadd(constT&c);voidremove(constT&c);NodeT*find(constT&c)const;voidprint()const;~List();};16:15:4515与类定义相似,成员函数的定义一般放在类定义的外部,与类定义分开.以有利于程序的组织.放在模板类定义外部的成员函数的定义形式为:templatetypenameTListT::List():first(0),last(0){}templatetypenameTvoidListT::add(constT&n){NodeT*p=newNodeT(n);p-next=first;first=p;(last?p-next-pref:last)=p;}List构造函数16:15:4516类模板(classtemplate):侧重于模板的描述(声明或定义),例如:TemplatetypenameTclassList;//类模板声明templatetypenameT//类模板定义classList{NodeT*first,*last;public:List();voidadd(constT&c);voidremove(constT&c);NodeT*find(constT&c)const;voidprint()const;~List();};模板类(templateclass):侧重于模板的使用形式例如:ListT//T为类型形参ListDog//Dog是类型实参形如ListT形式的类,不管T是形参还是实参,本书都称之为为模板类16:15:4517高级模板概念中,类模板声明,如:TemplatetypenameTclassList等同于带有形式类型参数的模板类,如:ListT并将其作为一种类型看待所以本质上不区分类模板与模板类.16:15:4518模板类的使用将直接透入对象的构造,因此,允许模板类带有值参便理所当然了.templateunsignedintNclassbitset;但是类型值参将导致不同的类模板描述,因而决定了不同的值参值,生成不同的模板类bitset100a;bitset200b;a=b;//error值参值应为编译能识别的常量,值参多为整型.16:15:45194.实例化与定做(Instantiation&Specialization)实例化遵循一次定义原则第一次用特定的类型实参使用模板类时,将引起类模板的实例化(产生类定义).ListdoubledList;//产生实例化ListdoubleeList;//不再实例化第一次用特定的类型实参使用模板函数时,将引起函数模板的实例化(产生函数定义).16:15:4520实例化与实施的操作有关,构造对象所触发的实例化,只实例化其构造函数,不实例化类模板的其他成员函数.但可以通过显式请求,强制整体实例化.templateListint;//实例化整个模板类ListdoubledList;//实例化构造函数dList.add(3.6);//实例化add成员dList.add(5.8);//不再实例化,只是简单调用ListintiList;//不再实例化iList.add(5);//不再实例化16:15:4521对于特定的类型实参,希望其行为不同于类模板所规定的操作,可以根据该实参来定做,定做的模板称为模板铸件(或称特制模板),如:templateclassListCat{NodeCat*first,*last;public:List();voidadd(constCat&c);voidremove(constCat&c);NodeCat*find(constCat&c)const;voidprint()const;~List();};16:15:4522模板铸件可为类,亦可为模板.若为模板,则其定做称为局部定做.templatetypenameT1,typenameT2classA{...};局部定做1templatetypenameTclassAT,T{…};//AT,T为模板局部定做2templatetypenameTclassAT,Cat{…};//AT,Cat为模板使用时要注意:Adouble,CatdCat;//按AT,Cat匹配Adouble,doubledd;//按AT,T匹配ACat,CatcCat;//错:AT,Cat还是AT,T?16:15:45235.程序组织(ProgramOrganization)包含方式模板使用的方式,不但创建了模板函数定义或模板类定义,还实施了函数调用,或者创建了对象,实施了对象操作.因此,除了需要函数模板声明或类模板定义之外,还需要函数模板定义和类模板的实现.也就是说,任何使用模板之前,编译应该能够事先看到整个模板的说明.这就是包含方式的由来.16:15:4524模板使用//x.cpp#include”tlist.h”intmain(){ListdoubledList;dList.add(3.6);dList.print();ListintiList;iList.add(5);iList.add(8);iList.print();}模板说明//tlist.h#ifndefTLIST#defineTLISTtemplatetypenameTstructNode{...};templatetypenameT//类模板定义classList{...};templatetypenameT//类模板成员函数实现ListT::List():first(0),last(0){}templatetype
本文标题:钱能C++程序设计教程14
链接地址:https://www.777doc.com/doc-4036634 .html