模板及其应用ppt课件.ppt_第1页
模板及其应用ppt课件.ppt_第2页
模板及其应用ppt课件.ppt_第3页
模板及其应用ppt课件.ppt_第4页
模板及其应用ppt课件.ppt_第5页
已阅读5页,还剩45页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第9章模板及其应用 9 1函数模板9 2类模板9 3关于类模板若干问题的说明9 4本章介绍函数模板与类模板的定义及其使用方法 通过使用模板 可使所编程序更加紧凑 增加程序的通用性及可重用性 1 9 1函数模板9 1 1函数模板的概念及说明9 1 2函数模板的应用举例 9 1 1函数模板的概念及说明 参看书p299 301通常设计的算法 处理语句 是可以处理多种数据类型的 但目前处理相同的问题 仍要分别定义多个类似的函数 2 intmax inta intb if a b returna elsereturnb doublemax doublea doubleb if a b returna elsereturnb charmax chara charb 3 实际上 若 提取 出一个可变化的类型参数T 则可 综合 成为如下的同一个函数 模板 它实际上代表着一组函数 Tmax Ta Tb if a b returna elsereturnb 在C 中定义完整的函数模板max时 格式如下 templateTmax Ta Tb if a b returna elsereturnb 4 函数模板定义的一般格式为 template返回类型函数模板名 形参表 函数体 注意 1 应在 返回类型 或 形参表 或 函数体 中使用上述的 类型形参名 2 调用处则类似于一般函数 用户只需给出具体的实参 3 模板函数调用时 不进行实参到形参类型的自动转换 5 9 1 2函数模板的应用举例 参看书p302 1 函数模板例1定义一个函数模板max 而后对它进行不同的调用 includetemplateTmax Ta Tb if a b returna elsereturnb 6 voidmain inti1 11 i2 0 doubled1 d2 cout d1 d2 cout max d1 d2 endl cout max 23 5 6 max 23 5 6 endl 出错 不进行实参到形参类型的自动转换 7 程序执行后的显示结果如下 inti1 11 i2 0 max i1 i2 0max 23 56 23charc1 T c2 F max c1 c2 Tmax f k kinputdoubled1 d2 123 4599 67d1 123 45 d2 99 67 max d1 d2 123 452 函数模板例2 函数模板与函数重载定义一个函数模板与一个函数 它们都叫做min C 允许这种函数模板与函数同名的所谓重载使用方法 但注意 在这种情况下 每当遇见函数调用时 C 编译器都将首先检查是否存在重载函数 若匹配成功则调用该函数 否则再去匹配函数模板 8 include includetemplatetypemin typea typeb type型的a与b要能够进行 比较运算 return a b a b char min char a char b 函数min 字符串型参数 不能直接使用 来进行比较return strcmp a b 0 a b voidmain cout min 3 10 endl 使用函数模板cout min 2 5 99 5 endl cout min m c endl char str1 TheCprogram str2 TheC program cout min str1 str2 endl 使用重载函数 9 3 函数模板例3 二函数模板重载定义两个函数模板 它们都叫做sum 都使用了一个类型参数Type 但两者的形参个数不同 C 允许使用这种函数模板重载的方法 注意 参数表中允许出现与类型形参Type无关的其它类型的参数 如 intsize includetemplateTypesum Type array intsize 求array数组前size个元素之和Typetotal 0 for inti 0 i size i total array i returntotal 10 templateTypesum Type a1 Type a2 intsize 求a1数组与a2数组前size个元素之和Typetotal 0 for inti 0 i size i total a1 i a2 i returntotal voidmain inta1 10 a2 8 floataf 10 为数组分量定值cout sum a1 10 endl 求出a1数组前10个元素之和并输出cout sum af 10 endl cout sum a1 a2 8 endl 求a1与a2数组前8个元素之和并输出 11 9 2类模板9 2 1一个队列类模板9 2 2类模板说明9 2 3使用类型参数和普通参数的类模板 12 9 3 1设计一个队列类模板 参看书p305 队列与栈不同 对数据采用 先进先出 FIFO的管理方式 而栈则使用 先进后出 FILO方式 队列数据放于作为类成员的动态数组queue之中 在构造函数中 将通过new来生成该动态数组 动态数组queue的大小由类的私有数据成员Maxsize之值来确定 但注意 此示例并没有循环使用上述的动态数组queue空间 即是说 队列中至多可以存放Maxsize个数据项 即使取走若干项后有了空闲空间后也不可重新进行使用 若稍加改造 使存取数据时首先通过对下标进行模Maxsize的运算 则可实现循环使用动态数组queue空间的功能 我们把它留作一个练习 13 include includetemplateclassQueue intMaxsize 队列的大小intfront rear 元素放在queue front 1 到queue rear 之中keytype queue 动态数组queue 用来存放队列数据public Queue intsize 构造函数 生成动态数组来存放队列数据Maxsize size queue newkeytype Maxsize front rear 1 意味着队列为空 14 intIsFull if rear Maxsize 1 return1 elsereturn0 intIsEmpty if front rear return1 elsereturn0 voidAdd constkeytype 15 Delete在类体外定义 函数名前要加类限定符 Queue templatekeytypeQueue Delete void if IsEmpty coutvoidQueue Add constkeytype 16 voidmain inti 0 QueueQi 10 QueueQf1 10 Qf2 10 while Qi IsFull Qi中只能盛10个数Qi Add 2 i Qi中 0 2 4 6 8 10 12 14 16 18Qf1 Add 3 0 i Qf1中 3 6 9 12 15 18 21 24 27 30 for i 0 i 4 i 四次循环 每次总 先往Qf2的队列尾部加入两个数 而后又从首部删取一个数并输出Qf2 Add 4 5 Qi Delete 从Qi首删取一元素 乘以4 5 而后将其加入到Qf2尾部 四次循环往Qf2队列尾加入 0 4 5 2 4 5 4 4 5 6 4 5 程序执行后的显示结果如下 01 593 17 9 2 2类模板说明利用类模板 带类型参数或普通参数的类 一次就可定义出具有共性的一组类 即 可使得所定义类中的某些数据成员 某些成员函数的参数 某些成员函数的返回值都可以是任意类型的 18 类模板定义格式如下 templateclass类模板名 带上述类型形参或普通形参名的类定义体 说明类型形参时 使用 class类型形参名 的方式 说明普通形参时 使用 普通形参名 的方式 注意 1 类定义体中应使用上述的 类型形参名 及 普通形参名 2 利用类模板说明类对象时 要随类模板名同时给出对应于类型形参或普通形参的具体实参 从而实例化为一个具体的类 说明格式为 类模板名注意 类型形参的相应实参为类型名 而普通形参的相应实参必须为一个常量 19 3 类模板的成员函数既可以在类体内进行说明 自动按内联函数处理 也可以在类体外进行说明 在类体外说明 定义 时使用如下格式 template返回类型类模板名 函数名 形参表 函数体 上述的 形参1的名字 来自于 形参1的说明 由 甩掉 说明部分的 类型 而得 是对类型形参或普通形参的使用 而 类模板名 所起的作用正是在类体外定义成员函数时在函数名前所加的类限定符 20 例如 对具有一个类型参数T的类模板TestClass 在类体外定义其成员函数getData时的大致样式如下 templateTTestClass getData 形参表 函数体 其中的 TestClass 所起的作用正是在类体外定义成员函数时在函数名前所加的类限定符 21 9 2 3使用类型参数和普通参数的类模板 1仅使用类型参数的类模板 includetemplateclassTestClass public Tbuffer 10 T类型的数据成员buffer数组大小固定为10 灵活性差 TgetData intj 获取T类型buffer 数组 的第j个分量 templateTTestClass getData intj return buffer j 22 voidmain TestClassClassInstA char取代T 从而实例化为一个具体的类charcArr 6 abcde for inti 0 i 5 i ClassInstA buffer i cArr i for i 0 i 5 i charres ClassInstA getData i cout res cout endl 23 TestClassClassInstF 实例化为另外一个具体的类doublefArr 6 12 1 23 2 34 3 45 4 56 5 67 6 for i 0 i 6 i ClassInstF buffer i fArr i 10 for i 0 i 6 i doubleres ClassInstF getData i cout res cout endl 程序执行后的显示结果如下 abcde2 113 224 335 446 557 6 24 2仅使用普通参数 非类型参数 的类模板示例 includetemplateclassTestClass public intbuffer i 使buffer的大小可变化 但其类型则固定为int 灵活性差 intgetData intj templateintTestClass getData intj return buffer j 25 voidmain TestClassClassInstF doublefArr 6 12 1 23 2 34 3 45 4 56 5 67 6 for i 0 i 6 i ClassInstF buffer i fArr i 10 for i 0 i 6 i doubleres ClassInstF getData i cout res cout endl 程序执行后的显示结果如下 21324354657 26 3既使用类型参数又使用普通参数的类模板示例 include include string h templateclassTestClass public Tbuffer i T类型的buffer 其大小随普通形参i的值变化 灵活性大 TgetData intj templateTTestClass getData intj return buffer j 27 voidmain TestClassClassInstA charcArr 6 abcde strcpy ClassInstA buffer cArr for inti 0 i 5 i charres ClassInstA getData i cout res cout endl 28 TestClassClassInstF doublefArr 6 12 1 23 2 34 3 45 4 56 5 67 6 for i 0 i 6 i ClassInstF buffer i fArr i 10 for i 0 i 6 i doubleres ClassInstF getData i cout res cout endl 程序执行后的显示结果如下 abcde2 113 224 335 446 557 6 29 9 3关于类模板的若干问题说明9 3 1静态成员及友元9 3 2特例版本9 3 3按不同方法来派生类模板 30 1 类模板的静态成员类模板也允许有静态成员 实际上 它们是类模板之实例化类的静态成员 也就是说 对于一个类模板的每一个实例化类 其所有的对象共享其静态成员 例如 templateclassC staticTt 类模板的静态成员t 类模板的静态成员在模板定义时是不会被创建的 其创建是在类的实例化之后 如 CAaiobj1 aiobj2 CAacobj1 acobj2 对象aiobj1和aiobj2将共享实例化类CA的静态成员intt 而对象acobj1 acobj2将共享实例化类CA的静态成员chart 9 3 1静态成员及友元 31 2 类模板的友元类模板定义中允许包含友元 我们讨论类模板中的友元函数 因为说明一个友元类 实际上相当于说明该类的成员函数都是友元函数 该友元函数为一般函数 则它将是该类模板的所有实例化类的友元函数 该友元函数为一函数模板 但其类型参数与类模板的类型参数无关 则该函数模板的所有实例化 函数 都是类模板的所有实例化类的友元 更复杂的情形是 该友元函数为一函数模板 且它与类模板的类型参数有关 例如 函数模板可以用该类模板作为其函数参数的类型 在友元函数模板定义与相应类模板 的类型参数 有关时 该友元函数模板的实例有可能只是该类模板的某些特定实例化 而不是所有实例化 类的友元 9 3 1静态成员及友元 32 大多数类模板不能任意进行实例化 也就是说类模板的类型参数往往在实例化时不允许用任意的类 类型 作为 实参 模板的 实参 不当 主要会在实例化后的函数成员调用中体现出来 例如templateclassstack 栈中元素类型为T的stack类模板Tnum MAX num中存放栈的实际数据inttop top为栈顶位置public stack top 0 构造函数voidpush Ta num top a 将数据a 压入 栈顶voidshowtop 显示栈顶数据 模板中通用的showtop 显示栈顶的那一个T类型的数据 必须为可直接通过运算符 来显示的数据 if top 0 cout stackisempty endl elsecout Top Member num top 1 endl 9 3 2特例版本 33 在上面的类模板stack中 以下的实例化都是可行的 stacki1 i2 stackc1 c2 stackf1 f2 等等 但如果采用用户定义类型而又未在该类中对运算符 com1 com2 由于在执行com1 showtop 函数时 将需要对complex类型的数据num top 1 通过使用运算符 就是不可行的了 9 3 2特例版本 34 如果用户在上述情况下 需要使stack可行 可有几个办法 对于类complex追加插入运算符 showtop 专用于complex类型的showtop 专门补充的 特例版本 显示栈顶的 那一个complex型数据 其中的stack为一个实例化后的模板类 if top 0 cout stackisempty endl elsecout Top Member num top 1 get r num top 1 get i endl 9 3 2特例版本 35 假设自定义的复数类型complex中具有公有的成员函数get r 以及get i 用于获取复数的实部和虚部 如此 当实例化stack时将按该特例版本的定义进行 概括地说 当处理某一类模板中的可变类型T型数据时 如果处理算法并不能对所有的T类型取值做统一的处理 此时可通过使用专门补充的所谓特例版本来对具有特殊性的那些T类型取值做特殊处理 也可以对函数模板 或类模板的个别函数成员补充其 特例版本 定义 例如 可将该例的showtop功能进一步划分 让showtop调用另一个新增加的show函数 而由show函数具体考虑对两种情况的处理 一种处理可直接通过运算符 来显示的数据 另一种 特例版本 专用于处理complex类型的数据 9 3 2特例版本 36 实例 classcomplex 复数类型complexdoublereal image public templateclassstack Tdata 20 inttop public voidshowtop void 显示栈顶数据 37 templatevoidstack showtop void 通用的showtop T类型数据 可直接通过 showtop void 专用于complex类型的showtop 显示栈顶的那一个complex型数据 它不可直接通过 一次性输出 if top 0 cout stackisempty endl elsecout Top Member data top 1 get r data top 1 get i endl 38 voidmain stacks1 for inti 1 is1c complexc1 1 1 1 111 c2 2 2 2 222 s1c push c1 s1c push c2 压入 复数c2 处于栈顶 s1c showtop 调用专门补充的 特例函数 showtop 39 通过继承可以产生派生类 通过继承同样可产生派生的类模板 1 一般类 其中不使用类型参数的类 作基类 派生出类模板 其中要使用类型参数 classCB CB为一般类 其中不使用类型参数 它将作为类模板CA的基类 templateclassCA publicCB 被派生出的CA为类模板 使用了类型参数T 其基类CB为一般类Tt 私有数据为T类型的public 9 3 3按照不同的方法派生类模板 40 2 类模板作基类 派生出新的类模板 但仅基类中用到类型参数T 而派生的类模板中不使用T templateclassCB CB为类模板 其中使用了类型参数T 它将作为类模板CA的基类Tt 私有数据为T类型的public Tgett 用到类型参数Treturnt templateclassCA publicCB CA为类模板 其基类CB也为类模板 注意 类型参数T 将被 传递 给基类CB 本派生类中并不使用该类型参数Tdoublet1 私有数据成员public 基类的名字应为实例化后的 CB 而并非仅使用 CB 例如 在本例的派生类说明中 要对基类进行指定时必须使用 CB 而不可只使用 CB 41 3 类模板作基类 派生出新的类模板 且基类与派生类中均使用同一个类型参数T templateclassCB CB为类模板 其中使用了类型参数T 它将作为类模板CA的基类Tt 数据成员为T类型的public Tgett 用到类型参数Treturnt templateclassCA publicCB CA为类模板 其基类CB也为类模板 注意 类型参数T将被 传递 给基类CB 本派生类中也将使用这同一个类型参数TTt1 数据为T类型的public 42 4 类模板作基类 派生出新的类模板 但基类中使用类型参数T2 而派生类中使用另一个类型参数T1 而不使用T2 templateclassCB CB为类模板 其中使用了类型参数T2 它将作为类模板CA的基类T2t2 数据为T2类型的public templateclassCA publicCB CA为类模板 其基类CB也为类模板 注意 类型参数T2将被 传递 给基类CB 本派生类中还将使用另一个类型参数T1T1t1 数据为T1类型的public 9 3 3按照不同的方法派生类模板 43 9 4程序实例 设计一个链表类模板 参看书p318 定义一个处理链表的类模板list 它含有一个类型形参T 以指出每一链表项的data数据域的类型 include include 44 templateclassli

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论