《面向对象程度设计基础(第2版)》第九章类属机制_第1页
《面向对象程度设计基础(第2版)》第九章类属机制_第2页
《面向对象程度设计基础(第2版)》第九章类属机制_第3页
《面向对象程度设计基础(第2版)》第九章类属机制_第4页
《面向对象程度设计基础(第2版)》第九章类属机制_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

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

文档简介

第九章

类属机制类属的作用类属类的定义与实例化类属类的继承关系类属函数的定义与实例化§9.1类属类属是实现编译时多态性的另一种机制,这种机制通过将数据类型参数化使得程序具有多态性类属机制的基本思想:实际应用中,一些函数的功能相同,唯一的区别只在于处理对象的数据类型不同,若用函数重载实现,则需编写多个函数:例:intmax(inti,intj) floatmax(floati,floatj) {returni>j?i:j;} {returni>j?i:j;}编程时只提供一套实现该功能的程序实体,然后将数据类型作为参数传递,这就是类属机制的思想C++语言中,使用模板来实现类属机制模板具有形式类属参数:将数据类型作为模板的参数,参数化的数据类型就是形式类属参数模板须经过实例化后才能使用:实例化是指用某一具体数据类型替代模板中的形式类属参数的过程,该确定的数据类型称为实际类属参数。C++语言的模板函数模板(类属函数)函数的形式参数表中某些形式参数的数据类型被参数化函数模板本身不是函数,经实例化后才得到函数类模板(类属类)类的数据成员的类型或成员函数的形参类型被参数化类属类也不是类,经实例化后才得到具体的类§9.2类模板

一、类属类的定义一般形式:template<class类属参数1,class类属参数2,…>class类名{

…};

形式类属参数表:用尖括号括起来的部分。用逗号隔开不同的形式类属参数,每个类属参数都由class引入类属参数在类的声明中有效,在类外无效在类的定义中,把这些类属参数当数据类型来声明各种变量例1:用类模板对数组进行排序、检索和求和#include<iostream.h>template<classT> // 声明一个形式类属参数TclassARRAY{ T *set; //定义数组元素集合

int n; //定义数组元素个数public: ARRAY(T*data,inti) { set =data; n =i; } ~ARRAY(){} voidsort(); //排序

intseek(Tkey); //检索

Tsum(); //求和};template<classT> //注意在类外声明类模板的voidARRAY<T>::sort() //成员函数的形式{

inti,j; Td; for(i=1;i<n;i++)//冒泡排序

for(j=n-1;j>=i;j--){ if(set[j-1]>set[j]){//交换set[j-1]和set[j]的值

d =set[j-1]; set[j-1] =set[j]; set[j] =d; } }}template<classT>intARRAY<T>::seek(Tkey){ for(inti=0;i<n;i++) if(set[i]==key)returni;//找到,则返回key在数组中的位置

return-1; //找不到,返回-1}template<classT>TARRAY<T>::sum(){ T s=0; for(inti=0;i<n;i++) s +=set[i]; returns;}例2:条件编译预处理命令

#ifdef标识符1 程序段1 #else

程序段2 #endif若标识符1已用define宏定义过,则程序段1参与编译,否则编译程序段2,在编译阶段实现分支结构例:#include<iostream.h>#defineMAXvoidmain(){ inta,b,t;

cout<<“Inputtwointeger:”;

cin>>a>>b;#ifdefMAX t=a>b?a:b; //如定义了MAX,则求最大值#else

t=a<b?a:b; //如没有定义了MAX,则求最小值#endif

cout<<t;}//条件编译预处理命令的另一种形式#ifndef标识符1 若标识符1未用define宏 程序段1 定义过,则程序段1参与#else

编译,否则编译程序段2

程序段2#endif两种形式的条件编译都可省略else分支例:#ifndefTEST_DEF 若TEST_DEF未定义,则中#defineTEST_DEF

间的这段程序参与编译,在classTEST_DEF{

该程序段中,首先宏定义……

TEST_DEF,当下次程序再次};

经过该处时,TEST_DEF已#endif 定义过,于是不再编译。保证该程序段在整个工程中只被唯一的编译一次二、类属类的实例化类模板不是类,不能用于创建对象,只有经过实例化后才得到类实例化的一般形式: 类属类名字<实际类属参数表>

例: STACK

类模板,不能用于创建对象 STACK<int> obj; 实例化:用实际类属参数int替换形式类属参数ELEMENT_TYPE后,得到一个整形堆栈类,即可用于声明对象。一个类模板可以实例化为多个不同的类例1中声明的ARRAY类模板的实例化voidmain(){ inti; intIData[10]={4,2,5,3,10,-4,-5,-2,0,-3};

ARRAY<int>

myArray(IData,10); cout<<"IData["<<myArray.seek(-5)<<"]=-5"<<"\n"; cout<<"SumofIDatais:"<<myArray.sum()<<"\n"; myArray.sort(); for(i=0;i<10;i++) cout<<IData[i]<<"";}输出结果:Idata[6]=-5SumofIDatais:10-5-4-3-20234510三、类属类的继承关系一个类模板可以作为一个普通类的派生类一个类模板也可作为其它类模板的基类例:#include<iostream.h>

//声明一个类属类作为基类。template<classTYPE>classBASE{public: voidshow(TYPEobj) {

cout<<obj<<"\n"; return; }};//声明一个类属类作为BASE的派生类。template<classTYPE1,classTYPE2>classDERIVED:

publicBASE<TYPE2>{public: voidshow2(TYPE1obj1,TYPE2obj2) {

cout<<obj1<<""<<obj2<<"\n"; return; }};

//演示类属类层次的用法intmain(){ DERIVED<char*,double>obj;//基类被实例化为BASE<double>

obj.show(3.14); //正确

obj.show2("Piis:",3.14159); //正确 //obj.show(“Hasanyerror?”); //类型错误 //

形参类型是double,实参类型是字符串

return0;}§9.3函数模板

一、类属函数一般形式:template<class类属参数1,class类属参数2,…>函数类型 函数名(形参表){ 函数体…}

例: template<classTYPE> TYPEmax(TYPEx,TYPEy) { return(x>y)?x:y; }

函数模板定义时应注意的问题在函数模板定义template中给出的每一个形式类属参数都必须出现在函数形参表中如: template<classT1,classT2> voidfun(T1x,T2y) {…… }

错误的用法template<classTYPE> template<classTYPE>TYPE*func()

voidfunc()

{……} {TYPEobj; …… }

对于类模板的成员函数则不做此项要求函数模板的实例化由编译系统根据函数调用的实际参数类型自动完成函数模板的实例化,不须显式实例化template<classTYPE>TYPEmax(TYPEx,TYPEy){ return(x>y)?x:y;}voidmain(){ MY_CLASS obj1,obj2; max(10,5); //用整型实例化

max(obj1,obj2); //用MY_CLASS实例化}调用类属函数时,应保证函数的实参类型与形式类属参数完全匹配因为函数模板在实例化过程中不做任何类型转换例:已知函数模板max的两个形参都是形式类属参数TYPE类型的,则以下两个应用错误max(10,10.5); 一个实参是整型,另一个是double型,类型不同max(10,obj1); 一个实参是整型,另一个是MY_CLASS类型都无法实例化二、类属函数的重载

例:#include<iostream.h>template<classTYPE>TYPEmax(TYPEx,TYPEy){ return(x>=y)?x:y;}template<classTYPE>TYPEmax(TYPEx,TYPEy,TYPEz){ TYPEw=(x>=y)?x:y; return(w>=z)?w:z;}template<classTYPE>TYPEmax(TYPEx[],intn){ TYPEm=x[0]; for(inti=0;i<n;i++) if(m<x[i]) m=x[i]; returnm;}voidmain(){ floatm,x=56,y=-55.8,z=99.1; intdata[10]={1,3,15,7,9,22,4,26,8,10}; m=max(x,y); //TYPE被实例化为float m=max(x,y,z);

intt=max(data,10);}在引入类属函数后,确定调用函数的哪个版本所遵循的匹配原则:(1)如果某一普通函数的形参类型正好与函数调用的实际参数类型匹配,则调用该函数。否则,(2)如果能从同名的类属函数实例化一个函数实例,而该函数的参数类型正好与函数调用的实际参数类型匹配,则调用该实例化的函数。否则,(3)对函数调用的实际参数作隐式类型转换后与非类属函数再作匹配,找到匹配的函数则调用它。否则,(4)提示语法错误。

例1:

#include<iostream.h>

template<classTYPE>voidswap(TYPE&x,TYPE&y)//声明一个函数模板swap{ TYPEtemp;

temp=x; x=y; y=temp; cout<<"Callinggenericversionofswap().\n";}

voidswap(int&x,int&y)//重载swap,定义一特殊版本(不是模板){ inttemp;

temp=x; x=y; y=temp; cout<<"Callingspecialversionofswap().\n";}

intmain(){ inti=10,j=20;floatx=1.44,

温馨提示

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

评论

0/150

提交评论