




已阅读5页,还剩57页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章函数和函数模板,C+语言的模块设计离不开函数,函数设计更离不开参数。在面向对象程序设计中,成员函数也是函数,只是它们的类型及其返回值更复杂些。由此可见,熟练地掌握函数知识,是非常必要的。掌握函数设计和调用的正确方法,是程序设计的基本功。正确设计函数原型和参数类型,不仅能保证函数的正确性,而且能提高程序设计的效率。本章除介绍函数调用,以及函数调用中的参数替换和返回值等问题之外,还讨论函数指针、内联函数、函数重载、函数模板等,但不涉及类的构造函数和成员函数。,3.1函数的参数及其传递方式3.2深入讨论函数返回值3.3内联函数3.4函数重载和默认参数3.5函数模板,主要内容,传递函数参数可使用传值和传引用(传址),传值又分为传数值和传地址值,传引用传递的就是地址。函数的参数还可以设计成默认形式,以方便使用。3.3.1(对象作为函数参数)传数值传数值是将实参的值传递给形参,形参拥有实参的一个备份,当在函数中改变形参的值时,改变的是这个备份中的值,不会影响原来实参的值。传数值方式可以防止被调用函数改变参数的原始值,这在很多场合是很重要的。注意,数组不能使用传数值方式。,3.1函数的参数及其传递方式,【例3.1】传数值不会改变原来值的例子。#include#includeusingnamespacestd;voidswap(string,string);/函数参数采用传数值方式voidmain()stringstr1(现在),str2(过去);swap(str1,str2);/传数值cout返回后str1=str1str2=str2endl;,3.1函数的参数及其传递方式,voidswap(strings1,strings2)stringtemp=s1;s1=s2;s2=temp;cout交换为:str1=s1str2=s2endl;虽然swap函数内交换str1和str2的值,但不影响原来的值,所以程序输出结果如下:直接使用一般的数据类型的对象,或者使用类和结构的对象作为参数,均是传数值方式。注意,数组不能使用传数值方式。,3.1函数的参数及其传递方式,传地址值传递的是指向参数的指针。实际上,形参传递的就是实参本身,当在函数中改变形参的值时,改变的就是原来实参的值。大多数程序设计者为提高运行效率,常使用传地址值方式。例如传递类或结构时,传递对象的地址值。指针可以指向对象的地址,所以传地址值要用到指针。数组名就是指针名,所以数组只能用传地址值的方式。【例3.2】传地址值改变原来值的例子。#include#includeusingnamespacestd;voidswap(string*,string*);/函数参数采用/传地址值方式voidmain(),3.1.2(对象指针作为函数参数)传地址值,stringstr1(现在),str2(过去);swap(因为实参与形参的地址相同,所以改变形参就是改变实参。输出结果如下:,注意:不要一定要在主程序里产生指针,然后再用指针作为参数。函数原型参数的类型是指针,可以直接让它指向对象地址,即string*s1=,voidswap(inta)inttemp=a0;a0=a1;a1=temp;cout交换为:a=a0b=a1endl;运行结果如下:,C+提供引用,主要是用来建立函数参数的引用传递方式。在说明引用参数时,不需提供初始值,其初始值在函数调用时由实参提供。传引用是将对象的引用作为参数传递,引用和被引用对象的地址一样,所以改变形参就是改变实参。【例3.4】通过传引用改变原来值的例子。#include#includeusingnamespacestd;voidswap(string/函数参数采用/传引用方式,3.1.3(引用作为函数参数)传引用方式,voidmain()stringstr1(现在),str2(过去);swap(str1,str2);/传引用cout返回后:str1=str1str2=str2n;/接收要处理的字符串数量stringstr=input(n);/将函数返回的对象赋给对象strcoutstrab;couty)?x:y;intmin(intx,inty)return(x=0.,函数isnumber很简单,但很有用,在许多程序中都要用到,但对于这样一个简单的函数,使用函数调用(尤其是程序中多次调用这个函数时)却大大降低了使用效率。为了提高效率,常常将函数main中对函数isnumber的调用替换成表达式,即if(c=0这种替换用手工来做是很繁琐的,可以让C+编译程序来做,这只要在函数isnumber的定义前加上关键字inline即可,即定义为:inlineintisnumber(charc)C+编译器在遇到对函数isnumber调用的地方都用这个函数体替换该调用表达式。使用关键字inline说明的函数称内联函数。在C+中,除具有循环语句、switch语句的函数不能说明为内联函数外(编译器会对这类错误给出警告信息),其他函数都可以说明为内联函数。,使用内联函数,加快了程序执行速度,但如果函数体语句多,则会增加程序代码的大小。使用小的内联函数在代码速度和大小上可以取得折衷,其他情况下取决于程序员是追求代码速度,还是追求代码的规模。由于编译器必须知道内联函数的函数体,才能进行内联替换,因此,内联函数必须在程序中第一次调用此函数的语句出现之前被编译器看见。例如,上面的程序可采用下述方式。#includeusingnamespacestd;inlineintisnumber(charc)return(c=0voidmain()/.,内联函数声明与使用总结,声明时使用关键字inline。编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销。注意:内联函数体内不能有循环语句和switch语句。内联函数的声明必须出现在内联函数第一次被调用之前。对内联函数不能进行异常接口声明。内联函数应该是比较简单的函数,结构简单、语句少.如果将一个复杂的函数定义为内联函数,反而会造成代码膨胀,增大开销.,3.4函数重载和默认参数C+允许为同一个函数定义几个版本,这称为函数重载。函数重载使一个函数名具有多种功能,即具有“多种形态”,称这种形态为多态性。在下面的例子中,为求两个数值中的最大者,设计一个名为max的函数,并为不同参数类型各设计一个函数体。同理,也可用这个函数名设计一个具有3个整型参数,从而求出3个整数最大值的函数体。当然,也可以为具有3个参数的max函数设计不同参数类型的函数体。【例3.12】函数重载产生多态性的例子。#includeusingnamespacestd;doublemax(double,double);/2个实型参数的函数原型intmax(int,int);/2个整型参数的函数原型charmax(char,char);/2个字符型参数的函数原型intmax(int,int,int);/3个整型参数的函数原型,voidmain()coutm2)?m1:m2;intmax(intm1,intm2)return(m1m2)?m1:m2;charmax(charm1,charm2)return(m1m2)?m1:m2;,intmax(intm1,intm2,intm3)intt=max(m1,m2);returnmax(t,m3);C+能够正确调用相应函数,程序输出结果如下:,从函数原型可见,它们的区别一是参数类型不同,二是参数个数不同。这种功能与自然语言中对动词的使用类似,此时的动词等价于C+的函数。例如一个对象在现实生活中可以对它进行清洁、移动、分解、修理或油漆,但这并不包括全部可用的动词(例如销毁)。而且并不知道动作将发生在哪些对象上,所以这些动词仅仅代表了一般性的动作。例如,尽管移动铅笔和移动桌子的概念相似,但它们所需要的操作并不相同。一个人可以移动铅笔,可能需要几个人移动大桌子,知道作用的对象是铅笔还是桌子之后,就能将它们与一系列的特殊操作联系起来。C+语言也只有向具有多态性的函数传递一个实际对象时,该函数才能与多种可能的函数中的一种联系起来。换句话说,源代码本身并不总是能够说明某部分的代码是怎样执行的。这说明C+的函数调用机制与ANSIC的不同。C+的多态性又被直观地称为“一个名字,多个函数”。源代码,只指明函数调用,而不说明具体调用哪个函数。编译器的这种连接方式称为动态联编或迟后联编。在动态联编中,直到程序运行时才能确定调用哪个函数。动态联编需要虚函数的支持,这将在虚函数中介绍。对【例3.12】而言,编译器在编译时,能根据源代码调用固定的函数标识符,然后由连接器接管这些标识符,并用物理地址代替它们,这就称为静态联编或先期联编。静态联编是在程序被编译时进行的。同理,可以设计一个求整数之和的函数。不过,如果要求4个整数之和,使用函数重载则需要编写3个函数。这时可编写一个具有默认参数的函数。,【例3.13】编写一个具有默认参数的函数。#includeusingnamespacestd;intadd(intm1=0,intm2=0,intm3=0,intm4=0)returnm1+m2+m3+m4;voidmain()coutadd(1,3),add(1,3,5),add(1,3,5,7)m2)?m1:m2;使用Type标识符来标识类型参数,即参数名是可以任意挑选的。尽管如此,字母T能使人联想到它是单词Type的第一个字母,所以一般都选T作为标识符。可把上面的函数重新改写为以下形式:,templateTmax(Tm1,Tm2)return(m1m2)?m1:m2;class意为“用户定义的或固有的类型”。字母T标识这个模板有一个参数类型。当在程序中使用max(2,5)时,编译器能推断出这个T为int,并使用如下版本产生具体的模板函数:intmax(intm1,intm2)return(m1m2)?m1:m2;而max(2.5,8.8)则使用如下版本:doublemax(doublem1,doublem2)return(m1m2)?m1:m2;由此可见,在调用函数模板时,函数参数的类型决定到底使用模板的哪个版本。也就是说,模板的参数是由函数推断出来的。,【例3.14】编制求两个数据中的最大值的函数模板程序。#includeusingnamespacestd;templateTmax(Tm1,Tm2)return(m1m2)?m1:m2;voidmain()cout(2,5)(2.0,5.)(w,a)(ABC,ABD)endl;程序输出结果为:55wABD,【例3.15】编写具有模板类参数的重载函数实例。#include#include#includeusingnamespacestd;voidprinter(complex);voidprinter(complex);voidmain()inti(0);complexnum1(2,3);complexnum2(3.5,4.5);printer(num1);printer(num2);,voidprinter(complexa)stringstr1(realis),str2=imageis;couta)stringstr1(realis),str2=imageis;coutstr1a.real(),str2a.imag()endl;【例3.16】使用类模板作为函数模板参数的程序。,#include#include#includeusingnamespacestd;templatevoidprinter(complexa)stringstr1(realis),str2=imageis;coutstr1a.real(),str2a.imag()endl;这里complex的参数已经类型参数化,所以功能比【例3.15】的重载函数强得多。使用上例的主程序,将得到同样结果。,2.函数模板的参数【例3.14】中的语句“max(2,5)”是使用显式地给出模板参数的比较准则。一般的格式为:函数模板名(参数列表)每次调用都显式地给出比较准则,也会使人厌烦。一般喜欢使用如下默认方式:函数模板名(参数列表)从而将main中的语句简化为:coutmax(2,5)tmax(2.0,5.)t“max(w,a)tmax(ABC,ABD)m2)?m1:m2;,template/必须重写Tmin(Tm1,Tm2)/求最小值return(m1(8.5,6)(2.3,5.8)(a,y)(95,121)endl;程序输出结果为:ABD,ABC,T,26,6,82,121,y,对于那些不标准的书写方式,就不能从函数的参数推断出模板参数。在【例3.24】中使用语句min(8.5,6),这需要min(double,int)的形式,与现在定义的模板参数不符,无法通过编译。定义的模板参数中的两个参数的类型必须一致,面对一个整数和一个实数,编译系统无法为它建立正确的模板函数,即无法实例化。这时也可以对参数表中的参数进行强制转换,语句min(8.5,(double)6)就是通过“(double)6”使它们的参数一致。更一般的方法是使用显示方式min(8.5,6)解决这一问题,从而能正确推断出模板参数。而显式调用方式max(95,121),则是输出字符。由此可见,显式规则可以用于特殊场合。,历年真题剖析,1.使用值传递方式将实参传给形参,下列说法正确的()A形参是实参的备份B实参是形参的备份C形参和实参是同一对象D形参和实参无联系考点:对象作为函数的参数,答案:A,2.在函数调用时,如某一默认参数要指明一个特定值,则有()A其之前所有参数都必须赋值B其之后所有参数都必须赋值C其前、后所有参数都必须赋值D其前、后所有参数都不必赋值考点:函数调用,答案:A,3.设存在函数intmax(int,int)返回两参数中较大值,若求22,59,70三者中最大值,下列表达式不正确的是()Aintm=max(22,max(59,70);Bintm=max(max(22,59),70);Cintm=max(22,59,70);Dintm=max(59,max(22,70);考点:函数重载,答案:C,历年真题剖析,4.下列哪个类型函数不适合声明为内联函数()A函数体语句较多B函数体语句较少C函数执行时间较短D函数执行时间过长,考点:内联函数的特点;,答案:A,5.intFunc(int,int);不可与下列哪个函数构成重载()AintFunc(int,int,int);BdoubleFunc(int,int);CdoubleFunc(double,double);DdoubleFunc(int,double);,考点:函数重载,答案:C,6.将指向对象的指针作为函数参数,形参是对象指针,实参是对象的_。,考点:对象指针作为函数的参数,答案:地址值,历年真题剖析,7.设函数voidswap(int&,int&)将交换两形参的值,如两整型变量inta=10;intb=15;则执行swap(a,b)后,a、b值分别为()A.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030动力锂电池正极材料技术路线选择与成本下降路径报告
- 2025-2030动力电池粘结剂材料性能指标升级与供应商认证门槛分析
- 2025-2030动力电池硅基负极材料产业化障碍与下一代高能量密度解决方案
- 青春期孩子沟通技巧与家长讲稿模板
- 2025-2030动力电池梯次利用技术标准与商业模式创新分析报告
- 2025-2030动力电池梯次利用储能系统安全标准制定进展
- 2025-2030动力电池固态化技术路线对比与产业化进程评估
- 2025-2030动力电池回收网点建设标准与运营效率提升研究报告
- 2025-2030动力电池回收网点布局与原材料溯源体系分析报告
- HR招聘面试技巧及测评模板
- 智能悬架系统集成开发关键技术与实践-2024-12-技术资料
- 应用PDCA降低药占比
- 分包商安全管理规定(4篇)
- 超重与失重+说课高一上学期物理人教版(2019)必修第一册
- 公司收取管理费协议书范本
- JTS-165-6-2008滚装码头设计规范-PDF解密
- 设备维修与保养(课件)
- 《电力行业数字化审计平台功能构件与技术要求》
- 医院培训课件:《和谐医患关系的建构与医疗纠纷的应对》
- 《肺癌基础知识课件》
- 会计继续教育《政府会计准则制度》专题题库及答案
评论
0/150
提交评论