6.1 函数的基本结构
函数是什么?函数在程序中就是,具备某些功能的一段相对独立的、可以被调用的代码。函数可以被一个函数调用,也可以调用另一个函数,它们之间存在着调用上的嵌套关系。
函数就是对复杂问题的一种“自顶向下,逐步求精”思想的体现。编程者可以将一个大而复杂的程序分解为若干个相对独立而且功能单一的小块程序(函数)进行编写,并通过在各个函数之间进行调用来实现总体的功能。
6.1.1 函数的声明、定义和调用
声明是告诉编译器一些信息,以协助编译器进行语法分析,避免编译器报错。而定义是告诉编译器生成一些代码,并且这些代码将由连接器使用,即声明是给编译器用的,定义是给连接器用的。
在C++程序中调用函数之前,首先要对函数进行定义。
函数的定义如下:
●返回类型:指数据类型,如int、float、double、bool char、void等,表示所返回结果的类型。若是void,则表示该函数没有结果返回。
●函数名:函数名是一个有效的C++标识符,函数名后面需要加一个(),用以区别变量名以及其他标识名。命名规则和变量命名一样,注意要能够表达出正确的意义。如果说一个变量命名重在说明它“是什么”的话,一个函数就重在说明它要“做什么”。
如果调用此函数在前,函数定义在后,就会产生编译错误。为了使函数的调用不受函数定义位置的影响,可以在调用函数前进行函数的声明。这样,无论函数是在哪里定义的,只要在调用前进行函数的声明,就可以保证函数调用的合法性。
声明一个函数的格式如下:
在C++中,除了主函数main由系统自动调用外,其他函数都是由主函数直接或间接调用的。函数调用的语法格式为:
其中的实际参数表是与“形参”相对应的,是实际调用函数时所定义的变量、常量或者表达式。
常见的函数调用方式有下列两种。
(1)将函数调用作为一条语句使用,只要求函数完成一定的操作,而不使用其返回值。若函数调用带有返回值,则这个值将会自动丢失。
(2)对于具有返回值的函数来说,把函数调用语句看作语句的一部分,使用函数的返回值参与相应的运算或执行相应的操作。
图6-1所示为函数调用的示意图。
图6-1 函数调用示意图
提示
函数的调用是可重复的,其结果不随调用的时间和地点的不同而改变。
下面通过一个实例来学习如何定义和调用函数。
【实例6-1】函数的定义(代码6-1.txt)
新建名为“hstest”的【C++ Source File】源程序,源代码如下所示:
【代码详解】
在程序中,定义了一个max函数,该函数的作用是比较参数x和y的大小,将x和y中较大的数作为返回值。在主程序中,首先从屏幕上输入x和y,再调用max函数,将x和y中较大的数值输出。
运行结果如图6-2所示。
图6-2 代码运行结果
【实例分析】
在本例中,在屏幕上输入两个数3和5,主程序调用3和5作为参数,调用max函数,返回3和5中较大的值,并且输出。
6.1.2 参数的传递方式
在上一节中,介绍了如何定义和调用函数。想必大家都注意到了,在调用函数时,在函数名后面都有一个调用这个函数的参数。在C++中,参数的传递方式有两种,一种称为值传递,另一种称为地址传递或引用传递。
1.值传递
所谓值传递,是指当一个函数被调用时,C++根据形参的类型、数量等特征将实参一一对应地传递给函数,在函数中调用。
在值传递的过程中,形参只在函数被调用时才分配存储单元,调用结束即被释放。实参可以是常量、变量、表达式、函数(名)等,但它们必须要有确定的值,以便把这些值传送给形参。实参和形参在数量、类型、顺序上应严格一致。传递时是将实参的值传递给对应的形参,即单向传递。
函数并不对传递的实参进行操作,即使形参的值发生了变化,实参的值也不会随着形参的改变而改变。
【实例6-2】值传递(代码6-2.txt)
新建名为“zcdtest”的【C++ Source File】源程序,源代码如下所示:
【代码详解】
在主程序中,首先声明了swap函数,定义了变量a和b,分别赋值为3和4,输出a和b的结果;调用swap函数交换a和b的值,再输出a和b的结果。在程序的最后,定义了swap函数,该函数将两个参数的值对调。
运行结果如图6-3所示。
图6-3 代码运行结果
【实例分析】
在本例中,从运行结果来看,在函数调用前后a和b的值都没有改变。首先,给对应的形参变量分配一个存储空间,该空间的大小等于int类型的长度,然后把a和b的值一一存入为x和y分配的存储空间中,成为变量x和y的初值,供被调用函数执行时使用。这种方式中,被调用函数本身不对实参进行操作,也就是说,即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。所以,调用函数前后,a和b的值没有改变。
2.引用传递
地址传递就是将函数的参数定义为指针类型,在调用该函数时必须传递一个地址参数给函数。
引用传递的作用是在改变形参值的同时改变实参的值。引用是一种特殊类型的变量,可看作变量的别名,引用的声明使用符号“&”。
【实例6-3】引用传递(代码6-3.txt)
新建名为“yytest”的【C++ Source File】源程序,源代码如下所示:
【代码详解】
在主程序中,首先声明了一个swap函数,该函数的参数传递的是两个变量的引用。在主程序中,定义了变量a和b,分别赋值为3和4,输出a和b的结果;调用函数swap交换a和b的值,再输出a和b的结果。在程序的最后,定义了swap函数,该函数将两个参数的值对调。
运行结果如图6-4所示。
图6-4 代码运行结果
【实例分析】
在本例中,a和b在调用swap函数后值已经互换了。以引用作为参数,既可以使得对形参的任何操作都能改变相应实参的值,又使函数的调用显得方便和自然。
6.1.3 函数的默认参数
C++允许在函数定义时给一个或者多个默认参数值。在调用该函数时,如果给出实参,就采用实参值;如果没有给定实参值,就调用默认参数值。
提示
默认参数只可在函数声明中设定一次。只有在没有函数声明时,才可以在函数定义中设定。
函数默认参数的特点是在调用时可以不提供或提供部分实参。
下面通过一个实例来看看默认参数的使用。
【实例6-4】默认参数(代码6-4.txt)
新建名为“mrcstest”的【C++ Source File】源程序,源代码如下所示:
【代码详解】
这个程序,首先定义了一个add函数,函数的功能是将两个参数相加的结果返回。在定义函数时,使用了默认参数,默认x的值为5,y的值为6。如果没有参数录入,就调用默认函数。在main函数中,首先定义了变量i,调用add函数,参数分别是10和20,将add函数的调用结果赋值给i,将i输出;调用add函数,没有参数,即默认参数分别是5和6,将add函数的调用结果赋值给i,将i输出;调用add函数,只有一个参数10,将add结果赋值给i,将i输出。
运行结果如图6-5所示。
图6-5 代码运行结果
【实例分析】
从结果来看,当输入的参数为10和20时,add函数就按照输入参数计算,结果就是30;第二次调用add函数时,没有输入参数,就按照默认参数5和6计算,结果就是11;第三次调用add函数时,输入一个参数10,第二个参数就取默认参数10,最后结果就是16。
6.1.4 函数的返回值
在C++中,函数通过return语句返回值,如return x。若没有返回值,则可以不写return或写不带表达式的return。
提示
函数是一个计算单位,它可以返回值,也可以不返回值而进行一系列计算。
C++函数的返回值分为以下几种情况。
●主函数main的返回值:如果返回0,就表示程序运行成功。
●返回非引用类型:函数的返回值用于初始化在调用函数时创建的临时对象。用函数返回值初始化临时对象与用实参初始化形参的方法是一样的。如果返回类型不是引用,在调用函数的地方就会将函数返回值赋给临时对象,且其返回值既可以是局部对象,也可以是求解表达式的结果。
●返回引用:当函数返回引用类型时,没有复制返回值。相反,返回的就是对象本身。