面向对象的程序设计c++第六章模板演示文档

上传人:1** 文档编号:360177 上传时间:2018-06-28 格式:PPT 页数:72 大小:1.18MB
返回 下载 相关 举报
面向对象的程序设计c++第六章模板演示文档_第1页
第1页 / 共72页
面向对象的程序设计c++第六章模板演示文档_第2页
第2页 / 共72页
面向对象的程序设计c++第六章模板演示文档_第3页
第3页 / 共72页
点击查看更多>>
资源描述
面向对象程序设计第六章 模板C+ Templates,杨卫东 左峥嵘华中科技大学 自动化学院,2017秋,参考资料,C+ primer 第四版Effective C+ 3rdC+ Templates(简体中文版).pdf,内容,模板的定义函数模板类模板标准模板库STL,问题提出,实现一个函数,输入2个变量,输出这两个变量中值比较大的元素。要求:此函数可以接受int, char以及double类型的参数。C语言实现:/函数1char MaxOfChar( char cNum1, char cNum2) return(cNum1cNum2)?cNum1:cNum2;/函数2int MaxOfInt( int iNum1, int iNum2) return(iNum1iNum2)?iNum1:iNum2;/函数3double MaxOfDouble( double dNum1, double dNum2) return(dNum1dNum2)?dNum1:dNum2;,C语言,函数重载,c+时代,由于存在重载的概念,所以实现起来应该是这个样子:/函数1char Max( char cNum1, char cNum2) return(cNum1cNum2)?cNum1:cNum2;/函数2int Max( int iNum1, int iNum2) return(iNum1iNum2)?iNum1:iNum2;/函数3double Max( double dNum1, double dNum2) return(dNum1dNum2)?dNum1:dNum2;#define MAX(x,y) ( (xy) ? x: y ),函数名字统一但代码量没有什么变化能否进一步?,C+,宏定义,宏定义#define Max( Inputl, Input2) ( ( InputlInput2) ? Inputl:Input2 )宏无类型检查,不建议,模板(函数模板) templateT Max( const T 可以接受任何类型的参数,包括上边提到的int, char, double,甚至任何自定义类型(只要你实现了它的比较运算符operator ) 具体选用什么样的实际函数是在编译时刻就决定好的,丝毫不会影响运行时的效率,Input参数中用的是const&的,好处是减少函数调用时候的开销,因为我们不知道T类型到底有多大,模板定义,代码重用是程序设计的重要特性,为实现代码重用,使得代码具有更好的通用性,需要代码不受数据类型的限制,自动适应不同的数据类型,实现参数化程序设计。模板是C+中进行通用程序设计的工具之一模板是C+支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型如希望函数或类能够处理多种不同类型数据,可以通过模板为函数或类设计一个通用样板(通用数据类型),当处理实际数据时,根据给定数据的实际类型来确定,模板是c+语言最强大却最少被使用的特征之一,便于重复利用已经开发好的数据结构和算法,可以提高代码的复用性和开发效率,是通用编程实现方法之一。 在c+中,模板让程序员能够定义一种使用不同类型对象的行为。比如用模板类定义一种链表,那么通过不同的模板参数(在调用时提供),可以生成不同类型的链表 有点像宏,但是宏不是类型安全的,而模板是类型安全的分函数模板和类模板两种,模板的特点,6.1 函数模板 1、数据类型作为参数的背景例:求绝对值的函数int abs(int x)return x0?-x:x;double abs(double x)return x0?-x:x;特点:算法完全相同,仅仅只是数据类型不同。(函数重载)问题:能否以数据类型作为参数,实现通用代码设计。,2、模板模板是由可以使用任何数据类型的通用代码构成。模板以数据类型作为参数。模板的定义形式是:template 函数定义说明:template是关键字,表示定义的是模板。括起来的是模板的参数,可以有一个或多个。如:template 或者:template,3、例子 定义一个求绝对值函数的模板。#include template T abs(T x)return x0?-x:x;void main()int n=-5;double d=-5.5;coutabs(n)endl;/由n的类型为int推导出T为intcoutabs(d)endl; /由d的类型为double推导出T为double,分析:编译器调用abs()时,用其实参的类型推导出函数模板的类型参数。当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数。以abs(n)调用为例,编译器将生成一个函数:int abs(int x)return x, 2 _TD31;,举例2矩阵,template class Matrixpublic: / constructors and destructor Matrix(); Matrix( const Matrix ,Test62_TmatrixsDemo.dsw,模板是C+支持参数化的工具使用类模板使用户可以为类声明一种模式,使类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能够取任意类型。类模板的声明形式如下: template 类声明模板参数表为:class 标识符;如:template 模板参数表包含上面多项内容时,各项内容以逗号分隔。模板类的成员函数必须是函数模板,6.2 类模板,在类模板首部以外的成员函数定义都要以下面的形式开头。 template 与函数模板相同,类模板只有使用的时候才被具体化为某一种类型用模板类创建对象的一般形式: 模板 对象名1,对象名2,对象名n; 模板参数表为用逗号分隔的若干类型标识符或常量表达式构成。,6.2 类模板,#include #include / 结构体Studentstruct Student int id; /学号 float gpa; /平均分; template /类模板:实现对任意类型数据进行存取class Store private: T item; / item用于存放任意类型的数据 int haveValue; / haveValue标记item是否已被存入内容 public: Store(void); / 缺省形式(无形参)的构造函数 T GetElem(void); /提取数据函数 void PutElem(T x); /存入数据函数;,举例,/以下实现各成员函数。/注意:模板类的成员函数,若在类外实现,则必须是模板函数/ 缺省形式构造函数的实现template Store:Store(void): haveValue(0) / 提取数据函数的实现template T Store:GetElem(void) / 如果试图提取未初始化的数据,则终止程序 if (haveValue = 0) cout No item present! endl; exit(1); return item; / 返回item中存放的数据 ,/ 存入数据函数的实现 template void Store:PutElem(T x) haveValue+; / 将haveValue 置为 TRUE,表示item中已存入数值 item = x; / 将x值存入itemvoid main(void) Student g= 1000, 23; /定义Student类型结构体变量的同时赋以初值 Store S1, S2; /定义两个Store类对象,其中数据成员item为int类型 Store S3;/定义Store类对象S3,其中数据成员item为Student类型,Store D; /定义Store类对象D,其中数据成员item为double类型 S1.PutElem(3); /向对象S1中存入数据(初始化对象S1) S2.PutElem(-7); /向对象S2中存入数据(初始化对象S2) cout S1.GetElem() S2.GetElem() endl; /输出对象S1和S2的数据成员 S3.PutElem(g); /向对象D中存入数据(初始化对象D) cout The student id is S3.GetElem().id endl;/输出对象S3的数据成员 /D.PutElem(6.5); cout Retrieving object D ;cout D.GetElem() item2 ? item1: item2; maxitem=maxitemitem3? maxitem: item3; return maxitem;#endif/EXAMPLE9_1.CPP/主程序#include #include EXAMPLE901.H#include EXAMPLE901B.Hvoid main() Max nmyMax(1,2,3); Max dblmyMax(1.2,1.3,-1.4); coutnmyMax.GetMaxItem()endl; coutdblmyMax.GetMaxItem()ptrNext; /一般情况 return ptrTemp;/链表类构造函数,4个私有指针成员设置为空,链表初始长度设置为0,初始当前结点/初始位置为-1templateLinkedList:LinkedList(void):ptrFront(NULL),ptrTail(NULL), ptrPrev(NULL),ptrCurr(NULL),nListLength(0),nPosition(-1) /重载=号运算符templateLinkedList& LinkedList:operator=(const LinkedList& list),if(this!=,if(!ptrFront) /如果当前指针为空,链表为空直接返回 return; if(nPos=nListLength|nPosNextListNode(); ptrPrev=ptrFront; nStartPos=1; for(nPosition=nStartPos;nPosition!=nPos;nPosition+) /寻找该位置并使当前指针指向该位置, ptrPrev=ptrCurr; ptrCurr=ptrCurr-NextListNode(); /当前指针指向当前结点的后续结点templatevoid LinkedList:Next() if(ptrCurr) ptrPrev=ptrCurr; ptrCurr=ptrCurr-NextListNode(); nPosition+; /将数据为nItem的结点插入到链表头template,void LinkedList:InsertFront(const T,newListNode=GetListNode(nItem); ptrCurr-InsertAfter(newListNode); /将数据为nItem的结点插入到链表的当前位置之前templatevoid LinkedList:InsertAt(const T else /一般情况 ,newListNode=GetListNode(nItem); ptrPrev-InsertAfter(newListNode); if(ptrPrev=ptrTail) ptrTail=newListNode; nPosition=nListLength; ptrCurr=newListNode; /将数据为nItem的结点插入到链表当前结点之后templatevoid LinkedList:InsertAfter(const T if(!ptrCurr) /处理空链表的情况 ,newListNode=GetListNode(nItem); ptrCurr=newListNode; ptrFront=ptrCurr; else /一般情况 newListNode=GetListNode(nItem); ptrCurr-InsertAfter(newListNode); if(ptrPrev=ptrTail) ptrTail=newListNode; nPosition=nListLength; ptrCurr=newListNode; nListLength+;/删除链表中的当前结点templatevoid LinkedList:DeleteCurr(), ListNode *ptr; if(!ptrCurr) /处理空链表的情况 cerrNextListNode(); else /一般情况 ptr=ptrPrev-DeleteAfter(); if(ptr=ptrTail) ptrTail=ptrPrev; nPosition-; ptrCurr=ptr-NextListNode(); FreeListNode(ptr);,nListLength-;/删除链表中所有结点并释放资源templatevoid LinkedList:DeleteAll() ListNode *ptrCurrPos, *ptrNextPos; ptrCurrPos=ptrFront; while(ptrCurrPos) /循环处理删除链表中的各个结点 ptrNextPos=ptrCurrPos-NextListNode(); FreeListNode(ptrCurrPos); ptrCurrPos=ptrNextPos; ptrFront=NULL; ptrTail=NULL; ptrPrev=NULL; ptrCurr=NULL;,nListLength=0; nPosition=-1;/删除链表的头结点templateint LinkedList:DeleteHead() ListNode *ptr=ptrFront; if(ptrFront) ptrFront=ptrFront-NextListNode(); delete ptr; nListLength-; return 1; else /处理链表为空的情况 coutThe List is empty!ShowDate(); ptr=ptr-NextListNode(); if(nPosition=-1) /list为空 return; ptrPrev=NULL; ptrCurr=ptrFront; for(int nPos=0;nPos!=list.CurrPosition();nPos+) /将新链表的各个数据成员设置与原链表相同 ptrPrev=ptrCurr; ptrCurr=ptrCurr-NextListNode(); nPosition=nPos; nListLength=list.ListLength();,/获得下一个新结点,返回新结点地址templateListNode *LinkedList:GetListNode(const T,ptrCurr=ptrCurr-NextListNode(); /在链表中查找数据templateint LinkedList:Find(T/删除链表中满足条件的结点template,void LinkedList:Delete(T key) ptrCurr=ptrFront; ptrPrev=NULL; if(!ptrCurr) return; while(ptrCurr /在排序链表中插入新结点构成新的排序链表,templatevoid LinkedList:InsertOrder(T nItem) ListNode *newListNode, *next, /用于遍历链表 *prev; /next指向结点的前一个结点的指针 ptrPrev=NULL; ptrCurr=ptrFront; prev=ptrCurr; next=ptrCurr-NextListNode(); while(prev-ShowDate()=next-ShowDate() /如果原链表中所有结点均相等,则将结点/作为原链表的首结点 else if(prev-ShowDate()next-ShowDate() /降序排列时 ,while(ptrCurr) /寻找插入位置 if(nItem=ptrCurr-ShowDate() break; ptrPrev=ptrCurr; ptrCurr=ptrCurr-NextListNode(); if(!ptrPrev) InsertFront(nItem); else newListNode=GetListNode(nItem); ptrPrev-InsertAfter(newListNode); else /升序排列时 while(ptrCurr) /寻找插入位置 if(nItemShowDate() break; ptrPrev=ptrCurr; ptrCurr=ptrCurr-NextListNode(); ,(续),if(!ptrPrev) InsertFront(nItem); else newListNode=GetListNode(nItem); ptrPrev-InsertAfter(newListNode); #endif,应用类模板过程中,在类外实现成员函数时要注意不要漏写template 。同时,所有涉及类模板的地方都要用。,谢 谢 !,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!