面向对象程序设计第3章函数_第1页
面向对象程序设计第3章函数_第2页
面向对象程序设计第3章函数_第3页
面向对象程序设计第3章函数_第4页
面向对象程序设计第3章函数_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

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

文档简介

1、第3章函数主要内容函数的基本概念inline函数重载函数作用域和生存期名字空间函数的基本概念函数定义、声明、调用、返回3. 1函数的基本概念函数定义函数可以被看作是一个由用户定义的操作函数一般用一个名字表示,即函数名函数的操作数称为参数,由参数表指定函数的结果称为返回值,返回值的类型称为函数返回类型函数执行的动作在函数体中指定返回类型、函数名、参数表和函数体构成了函数定义函数定义的语法形式为:返回类型函数名(参数表)函数体函数的基本概念函数原型数名、函数返回类型和参数表构成了函数原型。函数原型规定了函数的接口,接口描述了调用函数时需要提供的参数的类型和个数,以及函数返回结果的类型。函数声明在调

2、用函数之前,必须声明该函数,否则会引起编译错误。函数声明的形式函数声明由函数返回类型、函数名和参数表构成在函数声明中,参数的名字不是必需的函数声明中的参数名也可以和函数定义中的参数名不同有意义的参数名可以提高程序的可读性intmin(intivall,intival2);intmin(intvl,intv2);intmin(int,int);函数声明函数声明和定义一个函数可以在程序中多次声明函数定义也可以被用作声明,但是函数在程序中只能定义一次函数声明的作用函数声明说明了函数的接口,它描述了函数必须接收的信息类型(参数表),以及它的返回信息类型(返回类型)函数的用户对函数接口编程函数返回类型可

3、以是内置类型、复合类型或用户自定义的类类型函数和内置数组不能用作返回类型,但是,可以返回函数指针和数组首地址函数必须指定一个返回类型 标准C+规定返回类型不能省略,没有指定返回类型的函数声明或定义会引起编译错误 如果函数不返回任何结果,可以将其返回类型声明为void。 main。函数的返回类型必须定义为int函数参数表函数参数表函数的参数表不能省略 如果函数没有任何参数,可以用空参数表或void参数表表示 参数表由逗号分隔的参数类型列表构成,每个参数类型之后跟一个可选的参数名字 如果参数没有名字,则该参数不能在函数体中使用函数的调用和返回函数调用函数之间通过相互调用来传递数据、协作完成程序的功

4、能main。函数可以调用其他函数,其他函数可以相互调用,但不能调用main()函数实际的函数调用发生在程序运行时:函数名后紧跟着调用操作符“()”时,该函数就被调用执行,如果函数定义要求接收参数,在调用这个函数时就需要为这些参数提供相应的数据,这称为向函数传递参数函数定义中的叁数被称为形式参数,筒称形参在调用函数时提供的数据称为实际参数,简称实参函数的调用和返回函数调用过程函数调用会使程序的控制权传递给被调函数,而当前活动函数的执行被挂起缺省情况下,函数的参数和返回值是按值传递的函数在运行时都会使用到程序运行栈中分配的存储区。这块存储区一直与该函数相关联,直到函数结束时,存储区自动释放。函数的

5、这个存储区被称为活动记录函数在执行完函数体的最后一条语句或遇到return语句时返回当被调函数执行完成时,主调函数从调用语句之后的语句恢复执行函数的调用和返回参数传递是指用函数调用的实参来初始化函数形参存储区的过程按值传递参数C+中默认的参数传递方式是把实参的值拷贝到形参的存储区中,即用实参值初始化形参,这称为按值传递。按值传递时,函数不会访问当前调用的实参,函数中处理的只是实参的拷贝,这些拷贝在运行栈中存储,改变这些值不会影响实参;函数执行结束后,函数的活动记录将从栈中弹出,这些局部值就消失了inttest(intleft,intright)returnleft+right;intmain(

6、)int1val=2;intrval=3;intresult=test(Ival,rval);)main活动 记录test活动 记录函数的调用和返回不适合传值的情况 当大型的类对象或结构体变量作为参数按值传递时,为对象在运行栈中分配空间并拷贝对象的时间和空间开销往往过大 如果必须要修改实参的值时,按值传递无法做到 例如,用swap函数交换两个变量的值是不可行的voidswap(intvl,intv2)(intt=vl;vl=v2;v2=t;函数的调用和返回传递指针参数 将要修改的数据的地址作为参数传递给函数,在函数中通过指针间接操纵主调函数中的数据,实现修改 这种参数传递方式从本质上说仍然是值

7、传递,只不过传递的是地址值而已 传递指针参数,交换两个变量的值voidswap(int*vl,int*v2)(int七=*vl;*vl=*v2;*v2=t;)函数的调用和返回传递引用参数 将参数声明为引用,将改变缺省的参数传递方式。 当参数是引用时,函数接收的不是值的拷贝,即形参是实参的引用,或者说是别名,函数操纵的形参是实参的别名,因而可以改变实参的值 在大多编译器实现中引用形参实际上和实参占据相同的内存空间 传递引用参数,交换两个变量的值voidswap(int&vl,int&v2)intt=vlvl=v2;v2=t;函数的调用和返回函数的调用和返回引用参数的用途通过传递引

8、用在函数内修改实参的值向函数传递一个大型的结构体变量或类对象按值传递大型对象时,在每次调用函数时都要拷贝大对象,效率比较低;使用引用作参数可以避免拷贝,但仍然可以访问实参对象将参数声明为const引用可以避免在函数内部修改实参主调函数返回额外的结果一个函数最多只能返回一个值,如果希望得到多于一个的结果,就需要通过函数的实参带回额外的值/女在数组中查找一个指定元素,如果存在,则返回它第一次出现的位置和它出现的次数,如果不存在,返回一1”/intlook_up(intintsize,intval,int&occurs)intloc=-1;occurs=0;for(intix=0;ix<

9、;size;+ix)if(aix=val)(if(loc=-1)loc=ix;+occtirs;)returnloc;函数的调用和返回参数传递方式的选择对于内置类型的小对象,传值的方式更简单直接如果想在函数内改变实参,可以使用传引用或传指针的方式。更多人倾向于使用传指针,这样虽然语法比引用复杂一些,但使用起来更清晰明确。对于类类型的对象,尽量使用引用传递参数,效率更高使用const限定可以避免实参被修改函数的调用和返回数组参数在C+中数组永远不会按值传递,数组作参数时,将传递数组第一个元素的地址数组的长度与参数声明无关如果在函数内部要使用数组的长度,那么应该将它作为单独的一个参数被调函数内对参

10、数数组的改变将应用到数组实参上可以通过将形参数组声明为const来表明不希望改变数函数的调用和返回 函数的执行结果由return语句返回 return语句放在函数体内,它结束当前正在执行的函数,将控制权返回给函数的调用者 return语句有两种形式return;return表达式;第一种形式用在返回类型为void的函数中,这时return语句不是必需的,它的作用主要是强制函数结束。隐式的return发生在函数执行完最后一条语句时。return语句的第二种形式返回函数的执行结果,可以是任意复杂的表达式,甚至也可以包含函数调用。函数的调用和返回声明了非void返回类型的函数必须返回一个值,否则会引

11、起编译错误。如果return的表达式类型与函数声明的返回类型不匹配,将尝试应用隐式类型转换;如无法转换,则产生一个编译错误。main()函数的返回类型定义为int 如果main。函数有返回值,就作为这个程序返回给系统的值 如果没有返回值,系统将接收到一个表示程序成功完成的值,通常是0 main()函数返回非0值表示错误函数的调用和返回 缺省情况下,函数的返回值是按值传递的,即得到控制权的函数将接收return语句中指定的表达式值的拷贝。 可以将函数声明为返回一个指针或引用,此时不需要对return语句中的表达式进行拷贝,而是返回对象本身 不能返回局部对象的指针或引用 返回引用的函数调用表达式可

12、以作为左值使用如果函数返回引用,则对返回值的修改会改变实际返回的对象,为了避免这种情况,可以将返回值声明为const#include <iostream> using namespace std;const int SIZE =6;int & put_val(int aQJnt n)( -if (n>=SIZE | n<0)(cout«Moutside of boundaries!*1;exit (1);)return an;)int main()int arraySIZ日;for (int i=0;i<SIZE;i+)put_val(array

13、j)=i*2;/function call is on the left for (int j=O;j<SIZE;j+) cout«arrayj« H H«endl; return 0;)O 02468 10 12345 1086420 2468 10 12arrayC0=0array1=2array121=4a»ay31=6array43=8array5=10函数之间的通信Pressanykeytocontinue程序中的函数之间可以通过两种机制进行通信使用全局对象使用函数参数和返回值全局对象全局对象在函数之外定义,在程序的任意地方都可以访问,是

14、程序各部分进行通信的一种方便机制依靠全局对象进行通信的缺点1 .使用全局对象的函数依赖于全局对象的存在和类型,这使得在不同环境中复用该函数更困难。2 .全局依赖增加了修改程序时引入错误的可能性,即使只修改局部也要求理解整个程序3 .全局对象的值很难监控,发生错误时难判断错误的位置C+增加的新函数特性inline函数、重载函数、缺省参数3.2inIine函数is有时在程序中有一些包含语句非常少的小操作,可以将其定义为函数例如,计算两个整数之中的较小值,定义为函数intmin(intvlzintv2)return(vl<v2?vl:v2);I将这样的小操作定义为函数的优点是可读性好、易于修改

15、、重用性好缺点是调用函数有额外的开销,如果频繁调用,比直接计算条件运算符要慢很多如何解决这样的问题?3. 2 i n I i ne函数C+的解决方案inline(内联)函数若一个函数定义为inline函数,则在编译时,它将在数的每个调用点被“内联地”展开,从而消除了普通函数调用的额外开销。但是调用inline函数仍然会进行函数参数类型检查,是函数调用的语义,因此比宏更安全。inIine函数在函数定义或声明中的返回类型前加关键字inline,就将函数指定为内联的inlineintmin(intvlfintv2)return(vl<v2?vl:v2);3.2inIine函数in/ne函数的适

16、用性 inline只适用于很小的且被频繁调用的函数复杂的函数,如递归函数,并不适合在调用点展开;函数体庞大的函数在调用点展开则会导致代码膨胀 inline关键字对编译器来说只是一个建议,是否采用内联由编译器决定inline函数的代码组织 inline函数的定义对编译器而言必须是可见的,以便编译器在调用点展开该函数在调用inline函数的源文件中,必须有inIine函数的定义inline函数的定义一般放在头文件中,在每个调用该函数的文件中包含该头文件#include<iostream>usingnamespacestd;inlinefloatarea(floatIn,floatwd)

17、/inlinefunctionreturnln*wd;inlinevoidprint(floatx)/inlinefunctioncout«HtArea=H«x«endl;intmain()(floatlength=3.0,width=4.0,a;cout«HComputingtheareaofarectangle:11«endl;cout«HnLength="«length;cout«ntwidth="«width;a=area(length,width);/area()isexpa

18、ndedhere.print(a);/print()isexpandedhere.cout«nnAfterincrementinglengthandwidthby1:H«endl;cout«MnLength="«(length+1);cout«HtWidth="«(width+1);a=area(length+1,width+1);/area()isexpandedhere.print(a);/print()isexpandedhere.return0;)3. 2inIine函数内联函数与带参宏比较其优点有: 可以

19、检测逻辑错误或运行错误; 内联是一种请求,而不是一定,程序员不必关心是否进行了内联。 编译阶段可以对内联函数进行类型转换,而预编译不能进行类型转换。不对内联函数进行展开的几种情况: 规模大的函数函数中包含循环 函数中包含switch或goto语句 递归函数函数中包含静态变量3.3缺省参数函数如何使函数调用更简便?如果有一个函数print (), 它的功能是以指定的进制 输出一个整数void print ( in七ival, int base )int x = 20;print ( x, 8 ); print ( x, 2 ); print ( X, 10);每次调用print函数时,都要指定进

20、制。但是,在多数情况下,都使用十进制形式,可仍然需要指定第二个参数为10。是否存在某种更简便的调用方法呢?3. 3缺省参数函数概念和语法 可以在函数声明中为参数表中的一个或多个参数指定缺省实参voidprint(intival,intbase=10) 缺省参数是一种虽然不普遍,但在多数情况下仍然适用的实参值 缺省参数使得在某些情况下函数的调用更简单和方便 在调用有缺省参数的函数时,对声明了缺省值的参数可以不提供实参,这时函数将使用缺省的参数值;也可以像普通调用一样为该参数提供实参,提供的实参将覆盖缺省的参数值3. 3缺省参数函数缺省参数的使用函数调用的实参按位置进行解析,所以只能对函数参数表尾

21、部的参数提供缺省值void f oo ( irrtx, in七 yz in七 z = 0void f oo ( imtx, in七 y = 1, irrt z = 0 );void foo( intx, in七 丫 = 1, irrt z );void foo( intx=1,irrt丫,irrtz=0);3. 3缺省参数函数缺省参数的使用 函数调用时,如果一个参数使用了缺省值,那么后面的所有参数都要使用缺省值。设计带缺省参数的函数要考虑参数表中参数的排列次序,使最可能使用缺省值的参数出现在后面,最可能使用用户指定值的参数出现在较前面。 参数的缺省值在函数声明中指定,而不是在函数定义中指定。

22、在一个源文件中,一个参数只能被指定一次缺省13.3缺省参数函数voidfunl(charx=s',inty=1,floatz=3.14);fun1();/Alldefaultsareusedsameas:fun1(ls',1,3.14);fun1(*+');/Firstdefaultisoverriddensameas:fun1C+'J,3.14);fun1(,:9);/Firstandseconddefaultareoverriddensameas:funlf%1,9,3.14);fun1('&',9,6.28)/Alldefaults

23、areoverriddenintcalc(inta,intb=O,intc=1);/Validfunctionprototype以下调用方式正确与否?x=calc(5);x=calc(5,-l);x=calc(5,-1,9);x=calc(5,9);x=calc();OTFFTFOTTTFF0TFTTF0TFTTFSIBvoidshowError(intx,char*message=MMemoryallocationerror!1*);/VALIDfunctionprototype以下调用方式正确与否?showError(l);showError(2,"Fileopeningerro

24、r!");showError();showError("DivisionbyOP);以下函数声明的方式是否正确?voidfun(floata,intb=0,charc);voidfun(floata,charc,intb=0);OTFQTTOftff3.4重载函数如何为一组表达相同概念的函数命名?有时需要定义一组函数,它们对不同类型的数据执行同样的一般性动作,表达相同的概念如果一个函数名只能定义一次,那么需要为每个函数给出一个唯一的名字,例如:intmin_int(intvl9intv2);charmin_char(charvl,charv2);doublemin_doub

25、le(doublevl,doublev2);对用户而言,这些函数只是同一种操作,并不关心其细节;而记忆这一组不同的名字会给程序员和用户带来不便。3.4重载函数语法和概念 C+的函数重载机制允许多个函数共享同一个函数名,但是针对不同的参数类型提供不同的操作。 如果两个函数的名字相同,并且在相同的作用域中声明,但是参数表不同,则它们是重载函数。 重载函数的名字相同,但它们的参数表必须不同:或者参数个数不同,或者参数类型不同 返回类型不能区分两个重载函数,因为调用时可以忽略函数的返回值intmin(intvl,intv2);intmin(intvl,intv2,intv3);charmin(char

26、vl,charv2);doublemin(doublevl,doublev2);3.4重载函数如果不同的函数名所提供的信息使程序更易于理解,就没有必要使用重载函数当一个函数名在某个作用域中多次声明时,编译器根据下面的规则判断这些函数是否重载: 如果两个函数的参数表中参数的个数或类型不同,则这两个函数是重载的。 如果两个函数的返回类型和参数表都精确匹配,则认为是同一函数的重复声明。 如果两个函数的参数表相同,但返回类型不同,则认为是错误的重复声明以下两个函数是函数重载吗?intfun(double,int);doublefun(double,int);0是O不是int add(int x, in

27、t y);float add(float x, float y);int add(int x, int y);int add(int x, int y, int z);提交differentdatatypesdifferentnumberofargumentintadd(intxjnty);intadd(inta,intb);intadd(intx,inty);voidadd(intxnty);in七 add(in七 x,int y) return x+y; float:add(floatxzfloaty)returnx-y;TIP:一般用相同的函数名表示相似或相同的功能./include<iostream>include<iomanip>usingnamespacestd;constintsize=10;voi

温馨提示

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

评论

0/150

提交评论