C++程序设计第4章 函数和预处理教学课件

函数和预处理教学课件,函数与预处理,,第,4,章,,,4.1,函数的概念,4.2,函数的定义和声明,,4.3,函数的调用,,4.4,函数的重载,3,,4.5,变量,,习题,4.6,内部函数和外部函数,,4.7,预处理命令,4,第,4,章,,函数与预处理,前面已经介绍了常量、变量、表达式和语句,这些都是组成程序的基本要素本章将着重介绍程序中的另外一个重要概念,——,函数对于一个大型的程序,为便于实现,一般分为若干程序模块,每一个模块实现一个特定的功能在,C++,语言中,模块的功能由函数来实现C++,程序通过函数将上述基本要素结合在一起,完成一定的功能函数的实现将有利于信息的隐藏和数据共享,节省开发时间,增强程序的可靠性本章介绍函数的定义、声明、调用以及如何使用函数等内容,此外还将简略介绍有关预处理的概念5,4.1,函数的概念,“函数”这个名词是从英文,function,翻译过来的,其实,function,的原意是“功能”顾名思义,一个函数就是一个功能当然,读者可能会联想到数学中的函数数学中的函数可以根据输入的数值求得一个确定的值与此类似,,C++,中的函数也可以根据输入的数据,返回一个结果值。
不同的是,,C++,中的函数涵盖的意义更加广泛,定义也更加灵活,不仅可以求值,还可以执行一组相关的操作在后文中,如不加说明,所涉及函数都是指,C++,中的函数一个函数就是一个语句的集合,这些语句组合在一起完成一项操作系统实际上按顺序执行了多条语句以返回所需要的结果6,4.1.1,使用函数的必要性,客观地说,函数是,C++,程序的构成基础从前面所遇到的程序来看,一个,C++,程序可由一个主函数,main(),和若干子函数构成,而且必须有一个,main(),函数因为任何一个,C++,程序都是从主函数(即,main(),)的左花括号开始执行,一直到,main(),的右花括号为止函数也是程序中的最小模块,可以重复使用7,4.1.2,函数的组成部分,,,函数由函数头和函数体两部分构成,而函数头又是由返回值类型、函数名和参数列表构成其一般形式如下[,数据类型,],),,<,函数名,> [<,形式参数列表,>] //,函数头,,{,,,语句,,//,函数体,,},,8,下面举个例子来帮助大家理解函数的概念例,4-1】,求出两个整数中的较小值include ,,using namespace std;,,int min(int x,int y) //,定义有参函数,min,,{,,int z;,,z=x 程序执行结果如图,4-1,所示图,4-1 【,例,4-1】,执行结果,,10,,1,)数据类型,,数据类型是指函数返回值的数据类型如,【,例,4-1】,中的,min,函数返回一个,int,型数据(即,int,型,z,),就称该函数的返回值类型为,int,型如果某个函数不返回任何值,则其返回值类型是,void,,定义这样的函数的目的不是求一个值,而只是执行一组操作在此读者只需记住:当函数名前面出现,void,型返回值类型时,函数体的末尾无,return,语句注意:,C,语言中规定,如果在定义函数时不指定函数类型,系统会隐含指定函数类型为,int,型,因此,在,C,语言中,,int min(int x,int y),可以简写为,min(int x,int y),,但,C++,取消了这一规定,要求在定义函数时必须指定函数的类型,这样做更加严格和安全11,2,)函数名,,函数名就是函数的名字,即函数的标识符既然是标识符,就必须遵循标识符的命名规则由变量的标识符可知,函数的标识符也只能由字母、数字以及下划线组成,并且不能以数字开头值得注意的是,在给函数命名时,应尽量使函数名体现出该函数的功能或寓意,因为一个准确、有意义的函数名可以提高程序的可读性。 3,)形式参数,,形式参数简称形参形参列表是包含在函数名后圆括号中的,0,个或多个以逗号分隔的变量定义它规定了函数将从调用函数中接收几个数据及它们的类型其中当函数形参个数为零时,称为无参函数;函数形参个数不为零时,称为有参函数之所以称为形参,是因为在定义函数时系统并不为这些参数分配存储空间,只有被调用时,向它传递了实际参数(简称实参),才为形参分配存储空间当然在调用结束后,形参所占用的存储单元又会被释放如,【,例,4-1】,中,变量,x,、,y,是形参,变量,a,、,b,是实参注意:,当形参个数不为,0,时,在定义相同类型的形参时,对于参数表中的每个参数,都要求明确地指定类型,如,min,(,int x,int y,)不能写成,min(int x,y),12,4,)函数体,函数体是一个用一对花括号“,{},”括起来的语句序列,它描述了函数实现一个功能的过程当函数体中有,return,语句时,函数执行完,return,后结束;当函数体中无,return,语句,即函数的返回值类型为,void,时,函数执行完最后一条语句遇到右花括号“,},”时结束在此对,return,语句作一些说明1,)一般来说,函数的返回值是通过函数中的,return,语句获得的。 return,语句将被调用函数中的一个确定值带回主调函数中,且,return,语句执行后,函数就结束了例如:,,{,,…,,return 0,;,,//,函数返回,,cout <<",函数结束!," < 函数执行完最后一条语句,遇到右花括号“,},”结束5,)一个函数体中可以有多个,return,语句,但每次只能通过一个,return,语句执行返回操作例如:,,int max(int x,int y) //,返回两个整数中的较大值,,{,,if(x>y),,return x;,,else,,return y;,,},,一个函数体中有多个,return,语句时,如,【,例,4-1】,中有两个,return,语句,每个,return,语句的返回值类型都应与函数定义一致15,4.2,函数的定义和声明,函数声明也称为函数原型声明,是指在函数尚未定义的情况下,先将函数的形式告知编译系统,以便编译能够正常进行函数的声明包括返回值类型、函数名和参数列表值得注意的是,函数的声明仅仅是一条语句,因此在函数声明后一定要加上分号与函数的声明不同,函数的定义除包含函数头外,还包括函数体,是一个独立的完整的函数单位函数的定义又称函数实现16,4.2.1,函数的定义,函数可以是系统预定义的,也可以是用户自定义的前者称为系统函数或标准库函数,后者称为用户自定义函数1,)系统函数,,系统函数是由编译系统提供的,用户不必自己定义这些函数就可以直接使用它们。 当然在调用时也无须声明,用户只需用,#include,命令包含相应的头文件即可例如,前面已经用到过,#include ,,其中,cmath,是一个头文件,在,cmath,文件中包括了数学库函数所用到的一些宏定义信息和对函数的声明17,2,)用户自定义函数,用户自定义函数时应满足函数的,4,个组成部分:返回值类型、函数名、参数列表和函数体从函数的形式看,可分为有参函数和无参函数例如:,/*,定义有参函数,f1*/,,int f1(int x) //,有参函数,函数头,,{ //,函数体,,……,,return 0; //,返回,0,值,函数结束,,},,/*,定义无参函数,f2*/,,void f2() //,无参函数,函数头,,{ //,函数体,,……,,} //,无返回值,函数结束,上面两个程序,都是函数的完整定义18,函数不能嵌套定义,即在函数体中不能定义另外一个函数下面的情形是不允许出现的:,,void function1(),,{,,int function2() //,错误!函数定义不允许嵌套,,{,,…,,return 0,;,,},,},,虽然函数不允许嵌套定义,但可以在函数体中声明另外一个函数。 下面的情形是可以出现的:,,void function1(),,{,,int function2(); //,正确!在函数,function1,中声明函数,function2,,},,读者不妨自己上机试一试19,4.2.2,函数的参数列表,前面已经提到,在函数的声明和定义中,函数的参数列表可以为空(即无参函数),也可以不为空(即有参函数)如果函数为无参函数,则可用空参数列表或带一个,void,关键字的参数列表例如:,,int function(),,{,,…,,return 0;,,},,int function(void),,{,,…,,return 0;,,},,20,这两种定义方式是等价的,都表示不接受任何参数如果函数为有参函数,则在声明函数时,参数列表中的每个参数可以有名字,也可以没有名字例如:,,int min(int x,int y);,,int min(int ,int );,,,这两种声明方式是等价的,都表示接受两个整型参数但在定义函数时,参数列表中的每个参数就必须给出名字,形如“,int min(int ,int ),”在编译时就会出错。 此外,此处的参数名也有其特殊的意义:一方面,便于程序阅读者阅读;另一方面,可以提示该参数的含义,开发者可以根据参数的名字传入合适的参数21,4.2.3,函数的声明,,C++,标准规定:函数在调用之前,必须先声明在,C++,中,当函数定义在前,函数调用在后时,调用前可以不必声明,因为编译器已经知道了该函数的全部信息例,4-2】,求两个整数之和include ,,using namespace std;,,int add(int x,int y) //,求两个整数相加函数的定义,,{,,return (x+y); //,函数返回两个整数的和,,},,int main() //,主函数,,{,,int a,b,c; //,声明,3,个整型变量,,cout <<"please enter two integers: " < 图,4-2,求两个整数之和的运行结果,,,当编译器由上而下顺序编译下来,到第,12,行调用函数,add,时,因,add,函数接受的参数类型、参数个数及其返回值都已经明确,所以不需要另外声明如果一个函数的定义在后,调用在前,此时在调用前必须声明函数的原型,否则编译将会出错23,#include ,,using namespace std;,,int main() //,主函数,,{,,int a,b,c; //,声明,3,个整型变量,,cout <<"please enter two integers: " < 24,如果输入,a,的值为,4,,,b,的值为,6,,那么程序的运行结果将与,【,例,4-2】,的结果相同例,4-3,中的第,8,行就是函数,add,的声明,当编译器编译到这行代码时,就会知道,add,函数的基本信息:函数名为,add,,需要接受两个整型参数,返回一个整数对比,【,例,4-2】,和,【,例,4-3】,之后,或许读者会提出这样的疑问:编程时把函数定义都写在调用之前,把,main,函数写在最后,岂不是就可以省略函数声明这一步了吗?但是,这样做在安排函数顺序时要投入很多精力,在复杂的调用中,一定要考虑好谁先谁后,否则将发生错误而且,,C++,程序都是从,main,函数开始执行的,将,main,函数放在程序的开头可提高程序的可读性因此有经验的编程人员一般都把,main,函数写在最前面希望读者养成对所有用到的函数作声明的习惯25,(,1,)函数声明的位置比较灵活,可以出现在该函数调用前的任何位置,且对函数的原型声明次数没有限制2,)其实可以简单地照写已定义的函数的首部,再加一个分号,就是对函数的声明3,)如果一个函数不是被多个函数调用,一般是在调用该函数的前一行代码处声明如,【,例,4-3】,中的第,8,行对,add,函数的声明就是较好的例子。 下面再对函数的声明作一些说明26,,C++,支持所谓的分别编译,这样程序可以由多个文件组成由前面的例题可知,对于只有一个源文件的简单程序,可以不需要函数声明,只要保证函数在调用之前定义即可但用户在以后的学习和工作中,将要面对的常常是一些复杂的大型程序,往往有很多源文件,而且一个源文件中定义的函数,往往会被其他源文件使用,因此就需要在其他源文件中声明该函数在有多个源文件的程序中,往往把函数的声明放在头文件中,而把函数的定义放在源文件中当别的源文件要声明函数时,只需用,#include,命令包含头文件4.2.4,在头文件中声明函数,27,(,1,)写一个头文件,function.h,,用来声明,add,函数,其内容如下int add(int x,int y); //,声明一个求两个整数之和的函数,add,,(,2,)写一个源文件,function.cpp,,用来定义,add,函数,其内容如下int add(int x,int y) //,定义,add,函数,,{ return (x+y); } //,返回两个数之和,,(,3,)在其他源文件中调用,add,函数时,先要包含头文件,function.h,,如在主函数中调用:,,#include "function.h" //,包含头文件,function.h,,也即声明函数,add,,……,,void main() //,主函数,无返回值,,{,,cout < 下面用求两个整数之和的,add,函数来举例说明,28,在创建函数时,定义一个函数的目的是使用它要想使用函数,就要调用它调用函数时,开发者应当按照形参列表为函数传入所需的实参4.3.1,函数调用的一般形式,,函数调用的一般形式如下函数名(,<,实参列表,>,),,例如,下面的语句:,,c=add(a,b); //,调用,add(a,b),,并将返回值赋给整型变量,c,,cout < 30,程序运行结果如图,4-3,所示图,4-3,在,main,函数中调用无参函数的结果,,,在,【,例,4-4】,中,当程序执行到第,6,行时,程序控制流就会转到被调用的,print_message,函数(即跳转至,9,行)当执行到,print_message,函数结尾大括号(第,14,行)时,又将控制权交还给调用者,即此程序中的,main,函数31,在,C++,中,形参就是函数定义时的参数,实参是函数调用时传入的参数在,4.1.2,中也曾提到,在定义函数时系统并不为形参分配存储空间,只有被调用时向它传递了实参,才为形参分配存储空间在调用结束后,形参所占的存储单元又会被释放实参才是程序运行时实际存在的参数例如,在,【,例,4-3】,中,参数,x,和,y,就是形参而通过调用,add,函数传入的变量,a,和,b,是实参4.3.2,函数的形参和实参,32,(,1,)形参和实参是相对的概念,有时会相互转化例如:,,void count_add(int a,int b) //count,函数,计算两个整数的和,,{,,int c=add(a,b); //,调用,add,函数,求两个整数,a,b,的和,,cout <<"c=" <