5.2 函数参数及原型
在5.1节中介绍到函数一般都带有参数列表,这个参数列表称为形式参数,而在调用函数时,实际的参数和形式参数将会有数据传递。
函数原型也称函数声明或函数模型。在主调函数中,如果要调用另一个函数,则须在本函数或本文件中的开头将要被调用的函数事先作一声明。声明函数就是告诉编译器函数的返回类型、名称和形参表构成,以便编译系统对函数的调用进行检查。
5.2.1 函数的参数及返回值
在介绍函数定义的一般格式中,提到了函数的参数列表,即在函数名后的一对圆括号()内的参数,称之为形式参数,简称形参;而在主函数中调用该函数时指定的参数称为实际参数,也称实参。简单地说,被调用函数与主调用函数之间的通信可以通过参数的传递来实现。
如代码清单5-1所示,函数定义语句int func(int n)中int n即定义了一个形式参数,而在主函数的调用语句cout<<"\nthe result:"<<func(n)<<endl;中,func(n)中的n即为实际参数。
注意
实际参数必须与形式参数的个数相同、数据类型相同,而且其对应顺序必须为一一对应,这在后续的参数传递中还将重点讲解。
获得函数的返回值是调用函数的目的,也就是说,在主函数中调用某一函数的目的就是要获得被调用函数的返回值,以便在主函数中使用。对于函数与其返回值的关系,就如同加工厂中机器与产品之间的关系,工人将原材料放入到加工机器中,加工后出来的是产品,如图5-3所示。
图5-3 函数返回值
对于函数也可以这样理解,加工机器就是函数,原材料就是实参,产品就是函数的返回值了,调用函数最终就是为了获得产品。例如,下列定义的函数swap():
在上述函数中,swap()的括号中定义的整型变量a、b就是函数的参数,该函数返回一个整型值,在函数中返回为0。
5.2.2 函数原型
在C++中,如果在使用函数前没有对函数进行定义,则必须对函数进行声明。函数原型声明用来指出函数的名称、类型和参数,其说明语句的一般形式为:
[<属性说明>]<函数类型><函数名>(<参数>);
其中各部分的含义如下:
●属性说明可以默认,一般为inline(内联函数)、static(静态函数)、virtual(虚函数)、friend(友元函数)等这几个关键词之一。
●函数类型是指函数返回值的类型。
●函数名为一个C++标识符。
●参数,也称形式参数(形参),要求形参在函数原型声明、定义和调用时数据类型、个数、顺序一致,各形参名可以不同。
函数原型声明一般出现在程序中函数的调用之前,其目的是使编译器知道该函数的各种属性,包括返回值类型、形参的个数和类型等,以便于检查函数调用的合法性。事实上,前面5.1.2节中讲解的函数定义包括函数原型声明及函数体。例如,如果有一个函数的定义如下:
那么正确完整的函数声明应为:
double func1(double x,int y,float z); //末尾要加上分号
也可以写为如下形式:
double func1(double,int,float); //函数声明中省略了形参名
或写为如下形式:
double func1(double a,int b,float c); //函数声明中的形参名与函数定义中的形参名不同
提示
读者可以看出,除了需在函数声明的末尾加上一个分号“;”之外,其他的内容与函数定义中的第一行(称函数头)的内容一样。
但是需要读者注意的是,函数声明是不能省略参数的类型的,也不能省略函数的返回值类型,或者改变参数顺序,因此,下列函数的原型声明都是错误的:
5.2.3 main()函数
每个C++程序都必须要有一个main()函数,main()函数也称为主函数,是C++程序中最重要的函数,所有完整可运行的C++程序都必须有一个唯一的main()函数。读者在使用main()函数之前,需要对以下两点注意事项有一个简单的了解,才能更好地使用main()函数。
●对于一些简单的问题,只用一个main()函数即可,程序的全部处理语句都放在其中。
●对于一些复杂的问题,需要进行模块化设计,即把一个复杂的问题分解成若干个相对简单的一些子问题。每个子问题由一个或多个函数来处理,而main()函数负责总控,调用相应的函数。
main()函数是一个特殊的函数。其中“main”是函数名,与其他函数一样,该函数也可以有返回值和参数表。在后续章节中将讨论main()函数的参数和返回值的使用问题,以下给出main()函数的最简单形式:
【范例5-2】main()函数的应用。该范例完整地体现了C++程序的结构,读者可根据注释仔细理解,其代码如代码清单5-2所示。
代码清单5-2
【运行结果】上述代码在Visual C++中执行,其运行结果如图5-4所示。
图5-4 使用main()函数
【范例解析】上述程序段首先声明了两个函数原型,再在main()函数中调用,而将两个函数的定义写在main()函数之后,但由于在main()函数中调用其之前已经声明过,因此这是允许的。事实上,这也是C++程序较为普遍的写法。
注意
main()函数是C++程序中唯一可以直接运行的函数,其他函数都直接或间接由其调用执行。C++程序的执行开始于main()函数,一个结构良好的C++程序也应该结束于该函数。
范例5-2的代码清单5-2是C++中一个较为普遍的示例,读者应仔细理解其写法。此外,在使用C++编写程序时,应注意如下的事项:
●C++程序中每个语句都以分号“;”结束,此处的分号为英文半角字符,在输入C++源程序时一定要注意不能写成全角,否则编译将不能通过。
●函数的定义中使用了花括号“{”和“}”,花括号作为函数体的开始和结束标记。使用花括号也是C++的特点之一,但一定要配对使用。
●main()函数是主函数,其作用是声明变量,接收用户从键盘输入的字符,如上面示例在主函数中调用函数计算圆的周长和面积,最后输出结果。
●main()函数中的cout命令是C++语言系统提供的用于控制显示输出的对象,通过它可以输出各种类型的数据,这在前面章节中已经介绍过了。
●main()函数中的cin命令是C++语言系统提供的用于控制数据输入的对象,通过它可以输入各种类型的数据,这在前面章节中已经介绍过了。
●程序中以“//”开始的部分为注解。
●程序最开始的一行,即#include<iostream.h>为C++的预处理命令,其作用是将头文件iostream.h中的内容插入进来,该文件包含了键盘输入和显示输出的有关信息。
提示
在C++中,使用#include命令较多,被称为预处理指令,是C++系统提供的一组指导编译的指令之一,在后面的章节中还将具体讲解。
5.2.4 带参数的main()函数
在前面的程序中main()函数都没有带参数,因此其圆括号中都是空的。实际上,main()函数是可以带参数的。在main()函数中允许带两个参数,一个为argc,整型数据类型,另一个是指向字符型的指针数组argv[]。这两个参数在main()函数头部声明的格式为:
其中,整型参数argc表示命令行中字符串的个数,指针数组argv[ ]指向命令行中的各个字符串。这两个参数可以用任何合法的标识符命名,但习惯上采用argc和argv表示。带参数的main()函数一般能在调用其时追加参数,如DOS命令中dir/s一样,其中的“/s”就是参数。
【范例5-3】带参数的main()函数的应用。该范例通过一个带命令行参数的示例代码来查看其具体的使用方法和功能,该范例实现输出当前文件的路径,其代码如代码清单5-3所示。
代码清单5-3
【运行结果】上述程序详细地说明了argc参数和argv[]数组中存储的内容,如果直接在Visual C++的环境中运行该程序,其结果如图5-5所示。
图5-5 带参数的main()函数执行(1)
但是,这并不符合带参数的main()函数要实现的功能,带参数的main()函数是要像DOS命令一样能够根据参数执行的。因此,可以在操作系统的DOS环境下执行该程序。在DOS下进入到目标可执行文件的路径后,输入文件名和参数。在该示例中,文件名为5-3,输入参数为abc和xyz,其运行结果如图5-6所示。
图5-6 带参数的main()函数执行(2)
【范例解析】根据图5-6的执行结果,读者可以看出,用户输入了两个字符串,因此argc的值为2,在字符串数组argv[]中将这两个字符串分别放入argv[1]和argv[2]中,而argv[0]中存储的是该程序的当前路径。至此,读者应该明白这两个参数的作用了。