C++程序设计课程介绍-第6章 过程封装--函数.ppt
《C++程序设计课程介绍-第6章 过程封装--函数.ppt》由会员分享,可在线阅读,更多相关《C++程序设计课程介绍-第6章 过程封装--函数.ppt(151页珍藏版)》请在三一办公上搜索。
1、第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,函数的用途,函数是程序设计语言中最重要的部分,是模块化设计的主要工具。每一个C+程序都要用到函数。即使你自己不定义新的函数,在每一个完整的C+程序中都必须有一个main()函数。在C+语言中,字符处理、字符串处理和数学计算都是用函数的方式提供的。,函数的例子,我们可以将像sin那样的函数想象成一个黑盒子,或一个小机器。如果你在它的上面放入一个“值”,在它的下面就会掉出“结果”上面的值称为参数,下面的值称为返回值,调用函数的一个例子,如果我们改变了
2、输入的参数,函数就能返回不同的值。函数的参数可以是常数、变量或表达式。图中我们将调用4次sin的结果加起来,并将其和存入变量total中。,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,如何写一个函数,函数定义函数的返回值:返回值类型应与定义中的类型标识符一致表示一个函数没有返回值,类型标识符用void。没有返回值的函数也称为过程,类型标识符 函数名(形式参数表)变量定义部分 语句部分,return 返回值;或 return(返回值);,eg.int max(int a,int b)if(a
3、b)return(a)else return(b);,函数体,函数举例无参数、无返回值的函数,打印一个由五行组成的三角形,*,void printstar()cout“*n”;cout“*n”;cout“*n”;cout“*n”;cout“*n”;,函数举例有参数、无返回值的函数,打印一个由n行组成的三角形,void printstar(int numOfLine),void printstar(numOfLine)int nunOfLine;int i,j;for(i=1;i=numOfLine;+i)cout endl;for(j=1;j=numOfLine-i;+j)cout;for(j
4、=1;j=2*i-1;+j)cout“*”;,函数举例有参数、有返回值的函数,计算n!,int p(int n)int s=1,i;if(n 0)return(0);for(i=1;i=n;+i)s*=i;return(s);,函数举例返回布尔量的函数,判断某一年是否为润年的函数,bool IsLeapYear(int year)bool leapyear;leapyear=(year%4=0),第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,函数的声明,所有函数在使用前必须被声明,以便让编译
5、器知道用户的用法是否正确。函数声明包括下列内容:函数名函数的参数类型函数的返回类型函数的声明被称为函数的原型,它的形式为:返回类型 函数名(参数表);参数表中的每个参数说明可以是类型,也可以是类型后面再接一个参数名。如:int max(int,int);int max(int a,int b);,函数说明规则,库函数在调用前需要include相应的头文件。自定义的函数在调用时需要进行函数原型说明。函数原型说明与函数首部写法上需要保持一致,即函数类型、函数名、参数个数和参数顺序必须相同。如果被调函数的定义在主调函数之前,可以不必加声明。如果在所有函数定义之前,在函数外部已经做了函数声明,则在主调
6、函数中无须再作声明。,函数调用,#include int max(int a,int b);main()int x,y;cin x y;cout b)return(a);else return(b);,函数原型说明,函数调用,函数实现,函数调用,#include int max(int a,int b)if(a b)return(a);else return(b);main()int x,y;cin x y;cout max(x+5,y-3);,函数调用,函数实现,无须函数声明,建议用前一种方式!,函数调用,函数调用形式 函数名(实际参数表)eg.max(x,y);注意:形式参数和实际参数的个
7、数、排列次序、类型要完全相同。实际参数可以是常量、变量、表达式,甚至是另一个函数调用传递方式:值传递 值传递:函数获得了主调程序参数变量值的拷贝。被调程序可以改变这些拷贝,但这对主调程序的环境没有影响。,函数调用,调用方式,1.作为语句:printstar();,2.作为表达式的一部分,如要计算 5!+4!+7!,x=p(5)+p(4)+p(7),3.作为函数的参数,printstar(p(5)+p(4)+p(7);,函数执行过程,在主程序中计算每个实际参数值将实际参数赋给对应的形式参数。在赋值的过程中完成自动类型转换。依次执行函数体的每个语句,直到遇见return语句或函数体结束计算retu
8、rn后面的表达式的值,如果表达式的值与函数的返回类型不一致,则完成类型的转换。用函数的返回值置换函数调用,继续主程序的执行,函数执行过程,int p(int);int max(int a,int b)main()int x,y;cin x y;cout n2?n1:n2);,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,数组作为函数的参数,设一程序有下列要求:读入一组数据到一数组,直到输入为0为止将数组的元素倒过来排显示数组元素,main()int listMAX_NUM;GetIntege
9、rArray(list);ReverseIntegerArray(list);PrintIntegerArray(list);,存在的问题:输入的数据量是可变的,如何设置数组的大小?函数GetIntegerArray和ReverseIntegerArray只能修改自己的形式参数,而不能修改实际参数。函数的参数是数组,函数如何知道数组中有效的元素个数?,问题一的解决方案,在main函数中定义一个足够大的数组。不管GetIntegerArray 中输入多少数据都不会下标超界定义一个变量,指出数组中真正有多少元素。这样在PrintIntegerArray 和ReverseIntegerArray 函
10、数中可以根据这个值进行操作。因此,要增加一个整型的形式参数,问题二的解决方案数组参数的传递机制,C+语言规定,数组作为参数传递时,传递的是数组元素的首地址。当用实际参数 list 调用函数 GerIntegerArray 时,是把 list 的首地址作为形式参数数组的首地址。如 list 的首地址为1000,在函数中 形参数组的首地址也为1000。因此在函数中对形参数组 的修改就是对数组list 的修改。,函数原型的确定,PrintIntegerArray 和ReverseIntegerArray 需要知道哪一个数组和数组里有多少元素。而GetIntegerArray 需要知道哪一个数组、允许
11、输入的最大元素个数,以及输入结束字符。该函数执行结束后应能返回有效的数据个数。数组传递本质上传递的是数组的起始地址,真正的元素个数是通过另一个参数表示,因此形式参数中不需要说明数组的大小。void PrintIntegerArray(int array,int n);void ReverseIntegerArray(int array,int n);int GetIntegerArray(int array,int max,int sential);,Main函数,int main()int IntegerArrayMAX+1,flag,CurrentSize;cout flag;Curren
12、tSize=ReadIntegerArray(IntegerArray,MAX,flag);ReverseIntegerArray(IntegerArray,CurrentSize);PrintIntegerArray(IntegerArray,CurrentSize);return 0;,ReadIntegerArray,int ReadIntegerArray(int array,int max,int flag)int size=0;cout arraysize;if(arraysize=flag)break;else+size;if(size max)cout 超过数组规模 endl;
13、return 0;return size;,ReverseIntegerArray,void ReverseIntegerArray(int array,int size)int i,tmp;for(i=0;i size/2;i+)tmp=arrayi;arrayi=arraysize-i-1;arraysize-i-1=tmp;,PrintIntegerArray,void PrintIntegerArray(int array,int size)int i;if(size=0)return;cout 逆序是:endl;for(i=0;isize;+i)cout arrayi t;cout
14、endl;,数组作为函数的参数小结,可以将整个数组传递给函数,这时实际参数用的是数组名。数组传递的实质是传递地址。把实际参数中的数组首地址作为形式参数中的数组的首地址数组在函数中的定义:函数原型应该体现参数是一个数组,所以用无数组大小定义的方括号表示数组。对形式参数数组指定规模是没有意义的。,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,默认参数,对于某些函数,程序往往会用一些固定的值去调用它.例如对于以某种数制输出整型数的函数print:void print(int value,int b
15、ase);在大多数情况下都是以十进制输出,因此base的值总是为10。C+在定义或声明函数时可以为函数的某个参数指定默认值。当调用函数时没有为它指定实际参数时,系统自动将默认值赋给形式参数。例如,可以将print函数声明为 void print(int value,int base=10);调用print(20)等价于 print(20,10),带有默认参数的函数的使用,C+在说明函数原型时,可以为一个或多个参数指定缺省值。调用此函数时,若缺省某一参数,C+自动以缺省值作为此参数的值。如:int special(int x=2,float y=1.5)调用时可用:special(5,3.2)/
16、x=5;y=3.2 special(6)/x=6;y=1.5 special()/x=2;y=1.5,带有默认参数的函数注意事项,缺省参数无论有几个,都必须放在参数序列的最后,例如:Int SaveName(char*first,Char second=”,char*third=”,char*fouth=”);在函数调用时,若某个参数省略,则其后的参数皆应省略而取其缺省值,带有默认参数的函数注意事项,对参数默认值的指定只有在函数声明处有意义。因为函数的默认值是提供给调用者使用的。在不同的源文件中,可以对函数的参数指定不同的默认值。例如对于上面的print函数,如果在某一个功能模块中输出的大多是
17、十进制数,那么在此功能对应的源文件中可以指定base的默认值为10。如果在另一个功能最模块中经常要以二进制输出,那么在此功能模块对应的源文件中可以指定默认值是2。,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,内联函数,在C程序中,可以用带参数的宏。宏本身不是函数,但使用起来象函数。用复制宏代码的方式代替函数调用可以提高速度。最大缺点是容易出错。函数内联用于取代C语言中带参数的宏,其目的是为了提高执行效率。对于任何内联函数,编译器在符号表里放入函数的声明(包括名字、参数类型、返回值类型)。如
18、果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在调用内联函数时,编译器直接用内联函数的代码替换函数调用,于是省去了函数调用的开销。,内联函数,目的:减少函数调用的开销作用:函数代码复制到程序中,#includeinline float cube(const float s)return s*s*s;int main()float side;cin side;cout cube(side)endls;return 0;,慎用内联函数,内联以代码复制(膨胀)为代价,省去了函数调用的开销,提高函数的执行效率。如果相比于执行函数体内代码的时间,函数调用的开销可以忽略不计,那么效率
19、的收获会很小。以下情况不宜用内联:如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,重载函数,在传统的C语言中,不允许出现同名函数。当要求写一组功能类似、参数类型或参数个数不同的函数时,必须给它们取不同的函数名 例如某个程序要求找出一组数据中的最大值,这组数据最多有5个数据。我们必须写四个函数:求两个值中的最大值、求三个值中的最大值、求四个值中的最大值和求五个值中的最
20、大值。我们必须为这四个函数取四个不同的函数名,例如:max2,max3,max4和max5。,函数重载,使参数个数不同、参数类型不同或两者兼而有之的两个以上的函数取相同的函数名 如int max(int a1,int a2);int max(int a1,int a2,int a3);int max(int a1,int a2,int a3,int a4);int max(int a1,int a2,int a3,int a4,int a5);,函数重载的实现,由编译器确定某一次函数调用到底是调用了哪一个具体的函数。这个过程称之为绑定(binding,又称为联编或捆绑)。编译器首先会为这一组重
21、载函数中的每个函数取一个不同的内部名字。当发生函数调用时,编译器根据实际参数和形式参数的匹配情况确定具体调用的是那个函数,将这个函数的内部函数名取代重载的函数名。,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,函数模板,如果一组重载函数仅仅是参数的类型不一样,程序的逻辑完全一样,那么这一组重载函数可以写成一个函数模板。所谓的函数模板就是实现类型的参数化(泛型化),即把函数中某些形式参数的类型定义成参数,称为模板参数 在函数调用时,编译器根据实际参数的类型确定模板参数的值,生成不同的模板函数。
22、,函数模板的定义,一 般的定义形式 template 返回类型 FunctionName(形式参数表)/函数定义体 模板形式参数表可以包含基本数据类型,也可以包含类类型(需加前缀class)template T max(T a,T b)return ab?a:b;,例子,假设我们需要一个计算数值幂次方的函数,名为power。该数值可以是整型、长整型或实型我们只接受正幂次方,如果是负幂次方,结果为0。如果没有模板,我们需要每种类型写一个函数,power函数的template版本,表示T是一种类型,而此类型将在调用此函数时才给予。,Template函数的调用方法,编译器根据实际参数的类型确定模板参
23、数的类型,生成一个模板函数,第6章 过程封装函数,函数自己编写函数函数的使用数组作为参数带默认值的函数内联函数,重载函数函数模版变量的作用域变量的存储类别递归函数基于递归的算法,标识符的作用域,一个标识符能被存取的程序部分,称为标识符的作用域标识符的作用域与程序块有关。所谓的程序块是带有声明的复合语句如右框中有两块,Int main(void)int a=2,b=3;cout a b;int a=4;cout a b;cout a b;,标识符的作用域续,在块中说明的标识符是局部的,仅能在本块中和内部的块中存取。当内部块与外部块有同名标识符时,在内部块中屏蔽外部块的同名标识符。在一个函数中,我
24、们不能存取主调程序的变量,即使知道该变量的名字。函数参数对该函数也是局部的,可以将它看成在块内,即函数体内说明的说明的变量。,局部变量和全局变量,局部变量:在块内定义的变量称为局部变量,即使是main函数中定义的变量也是局部的。全局变量:在所有的函数外面定义的变量称为全局变量作用范围:从定义位置到文件结束。如在作用范围外的函数要使用此变量,用关键词extern在函数内说明此全局变量。作用:方便函数间的数据传递请写出下列程序的执行结果:,int p=1,q=5,r=3;int f1()int p=3,r=2;q=p+q+r;cout“f1:p,q,r=“p q r;int f2()p=p+q+r
25、;cout“f2:p,q,r=“p q r;int f3()int q;r=2*r;q=r+p;cout“f3:p,q,r=“p q r;main()f3();cout“after f3:p,q,r=”p q r;f1();cout“after f1:p,q,r=“p q r;f2();cout“after f2:p,q,r=”p q r;,结果:,f3:p,q,r=1 7 6,after f3:p,q,r=1 5 6,f1:p,q,r=3 10 2,after f1:p,q,r=1 10 6,f2:p,q,r=17 10 6,after f2:p,q,r=17 10 6,全局变量的使用说明,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+程序设计课程介绍-第6章 过程封装函数 C+ 程序设计 课程 介绍 过程 封装 函数
链接地址:https://www.31ppt.com/p-2764991.html