1C++语法基础知识函数2函数一个C++程序是由若干个源程序文件构成,而一个源程序文件是由若干个函数构成,每个函数具有相对独立的功能。函数是面向对象程序设计中,对功能的抽象。3函数一个源程序可以由若干函数构成,但有且仅有一个main函数,函数与函数之间通过输入参数和返回值来联系。源程序从main函数开始执行直到main函数结束,其他函数都是由main函数直接或间接地调用执行。4函数定义返回值类型函数名(参数列表){函数体}5函数原型函数原型即函数声明,用来描述函数的返回值和参数类型。返回值类型函数名(参数表);C++规定:名字必须先说明后使用。因此,当一个函数调用出现在函数定义之前,必须先对函数进行原型说明。6调用函数的两种顺序函数的原型说明函数调用函数的定义(实现)intadd(int,int);intmain(void){add(10,20);add(10);return0;}intadd(intx,inty){returnx+y;}函数定义函数调用intadd(intx,inty){returnx+y;}intmain(void){add(10,20);add(10);return0;}7函数原型函数原型的功能:确定函数返回值的类型;确定函数参数的类型和个数;函数名代表该函数的函数体以及函数完成的功能。8函数调用C++程序由若干函数构成,各个函数的执行通过函数的调用来完成的。在调用函数时,大多数情况下,主调函数和被调函数之间有数据传递关系。函数之间的数据传递主要是靠函数参数进行,而对无参数函数的调用,一般没有数据传递。全局变量9函数调用在定义函数时,函数名后面括号内的变量名为“形式参数”(形参)。在调用函数时,函数名后面括号内的表达式为“实际参数”(实参)。引入函数后,使用者只需要知道函数的功能和使用方法,而不必关心函数的内部代码,从而方便源代码的共享;使用函数,也可减少程序的冗余和程序的目标代码。10C++函数的几个特点内联函数带缺省参数的函数函数重载11内联函数函数调用有一定的时间和空间开销,影响程序的执行效率。对于一些函数体代码不是很大,但又频繁地被调用的函数,C++引入内联函数来提高时间利用率。12定义内联函数的格式内联函数的一般定义格式:inline返回值类型函数名(参数列表){函数体}在程序编译时,编译系统将程序中出现内联函数调用的地方用函数体进行替换。引入内联函数可以提高程序的运行效率,节省调用函数的时间开销(调用函数时要进行现场保护的有关操作),是一种以空间换时间的方案。13定义内联函数的限制内联函数体内不能有循环语句和switch语句。内联函数的声明必须出现在内联函数第一次被调用之前。对内联函数不能进行异常接口声明。14内联函数的编译与执行情况源代码编译后运行Inline函数A:内联函数语句a1:语句a2:函数B:语句B1:语句x1:调用函数A语句B2:……语句x2:调用函数A语句BX:……函数B:语句B1:语句B2:……语句BX:……语句a1:语句a2:语句a1:语句a2:函数B:语句1:语句x2:……语句x4:……语句a:语句a1:语句a:语句a1:需要存储代码的空间较大依次执行语句,较快15非内联函数的编译与执行情况源代码及编译后执行时代码较短函数D:函数语句D1:语句D2:函数B:语句B1:语句Y1:调用函数D语句B2:……语句Y2:调用函数D语句BX:……函数D:函数语句D1:语句D2:函数B:语句B1:语句Y1:调用函数D语句B2:……语句Y2:调用函数D语句BX:……有函数调用过程,较费时16带缺省参数的函数C++允许在定义函数时给其中的某个或某些形参指定缺省值(默认值)(定义函数参数时赋初值),这样,当发生函数调用时,若指定实参则用该值;如果省略了对应位置上的实参的值时,则在执行被调函数时,以该形参的缺省值进行运算。引入缺省参数的目是为了让编程简单,让编译系统做更多的检查错误工作,同时增强了函数的可重用性。17例示例带默认参数的函数(一)//example1.cpp#includeiostream.hintsum(intnum=10)//带默认参数函数的定义{inti,s=0;for(i=1;i=num;i++)s=s+i;coutsumis:sendl;return0;}18例示例带默认参数的函数(二)//example2.cppintmain(){sum(100);//提供了实参值,输出结果为5050sum();//省略实参值,使用默认值10,输出结果为55return0;}19默认形参值的说明次序默认形参值必须从右向左顺序声明,并且在默认形参值的右面不能有非默认形参值的参数。因为调用时实参取代形参是从左向右的顺序。例:intadd(intx,inty=5,intz=6);//正确intadd(intx=1,inty=5,intz);//错误intadd(intx=1,inty,intz=6);//错误20默认形参值与函数的调用位置调用出现在函数体实现之前时,默认形参值必须在函数原形中给出;而当调用出现在函数体实现之后时,默认形参值需在函数实现时给出。例:intadd(intx=5,inty=6);intmain(void){add();//调用在实现前return0;}intadd(intx,inty){returnx+y;}intadd(intx=5,inty=6){returnx+y;}intmain(void){add();//调用在实现后return0;}21函数重载函数重载是指一个函数可以和同一作用域中的其他函数具有相同的名字,(多个函数使用一个相同的函数名)但这些同名函数的参数类型、参数个数、返回值、函数功能可以完全不同。编译系统将根据函数参数的类型和个数来判断使用哪一个函数。22例示例函数重载。//example215.cpp#includeiostream.hintabs(intx)//形参为整型{returnx0?x:-x;}doubleabs(doublex)//形参为双精度型{returnx0?x:-x;}longabs(longx)//形参为长整型{returnx0?x:-x;}23例示例函数重载。//example215.cppintmain(){intx1=4;doublex2=5.5;longx3=6L;cout“|x1|=”abs(x1)endl;//调用intabs(int)cout“|x2|=”abs(x2)endl;//调用doubleabs(double)cout“|x3|=”abs(x3)endl;//调用longabs(long)return0;}24重载函数的声明C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。例:形参类型不同intadd(intx,inty);floatadd(floatx,floaty);形参个数不同intadd(intx,inty);intadd(intx,inty,intz);25重载函数的注意事项不要将不同功能的函数声明为重载函数,以免出现调用结果的误解、混淆。这样不好:intadd(intx,inty);intadd(inta,intb);编译器不以形参名来区分intadd(intx,inty);voidadd(intx,inty);编译器不以返回值来区分intadd(intx,inty){returnx+y;}floatadd(floatx,floaty){returnx-y;}重载函数的形参必须不同:个数不同或类型不同。编译程序将根据实参和形参的类型及个数的最佳匹配来选择调用哪一个函数。26函数模板函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,简化重载函数的设计。也可以说函数模板是提供一组重载函数的样板。函数模板的定义格式:类型参数表不能为空,模板类型参数代表一种类型,由关键字class或typename后加一个标识符构成,表示后面的参数名代表一个潜在的内置或用户定义的类型。template模板类型参数表返回值类型函数名(参数表){函数体}27函数模板函数模板的定义举例:templatetypenameT//T为模板参数Tmax(Tx,Ty,Tz)//定义函数模板{Ttt;if(xy)tt=x;elsett=y;if(ztt)z;returntt;}28模板函数的生成函数模板是对一组函数的描述,它以任意类型为参数及函数返回值。它不是一个实实在在的函数,编译系统并不产生任何执行代码。当编译系统在程序中发现有与函数模板中相匹配的函数调用时,便生成一个重载函数,该重载函的函数体与函数模板的函数体相同。该重载函数称为模板函数。它是函数模板的一个具体实例,只处理一种惟一的数据类型。29【例】用函数模板求数组元素中最大值templatetypenameGroapGroapmax(constGroap*r_array,intsize){Groapmax_val=r_array[0];for(inti=1;isize;++i)if(r_array[i]max_val)max_val=r_array[i];returnmax_val;}类型参数Groap表示max()的返回类型,参数r_array的类型,以及局部变量max_val的类型。形参size表示r_array数组的长度。与函数声明不同,函数模板的声明必须含变量名。在程序运行中,变量名会被各种内置(基本)类型或用户定义类型所置换。模板参数表的使用与函数形式参数表的使用相同,都是位置对应。类型和值的置换过程称为模板实例化。30模板函数的生成函数模板根据一组实际类型或(和)值构造出独立的函数的过程称为模板实参推演。主程序intia[5]={10,7,14,3,25};doubleda[6]={10.2,7.1,14.5,3.2,25.6,16.8};intmain(){inti=max(ia,5);cout整数最大值为:iendl;doubled=max(da,6);cout实数最大值为:dendl;return0;}第一次调用时,Groap被int取代。第二次调用,Groap被double取代。在main()函数中,由调用函数模板而生成的函数,称为模板函数。31练习题定义一个函数模板,该模板的功能是对数组进行排(升)序。编写主程序,使用这个模板,对有15个元素的整形数组和有30个元素的字符数组进行排序。注意要有输出语句分别输出排序前后的数组元素排列情况。