标准库函数的函数原型都在头文件中提供,程序可以用#include指令包含这些原型文件。对于用户自定义函数,程序员必须在源代码中说明函数原型。
函数原型是一条程序语句,即它必须以分号结束。它由函数返回类型、函数名和参数表构成,形式为:
返回类型 function(参数表);
参数表包含所有参数的数据类型,参数之间用逗号分开。在C++中,函数声明就是函数原型。
函数原型和函数定义在返回类型、函数名和参数表上必须完全一致。如果它们不一致,就会发生编译错误。
函数原型不必包含参数的名字,而只要包含参数的类型。下面的函数原型声明是合法的。
int Area(int,int);
等价于:
int Area(int length,int width);
对于标准库函数(简称库函数)来说,编译器从来不把其实际代码看成是程序的组成部分。编译器能够确认是否正确地调用库函数,这是必要的。在头文件中内含的函数声明都是函数原型。
如果函数原型不正确,编译器会及时报告错误。
例如,对于程序chl_3.cpp,主函数中的函数调用写成:
c=max(a,b,56); //error:extra parameter in function call
则编译器将会报告一个“函数调用中遇到过多的函数参数”之错误。
又例如,下面的代码中,函数声明与函数定义的函数原型不一致:
void funcA(int,float);
void main()
{
int a;
float b;
funcA(a,b);
}
void funcA(int,int)
{
//...
}
该代码能够正确通过编译,因为函数声明的原型与函数调用相吻合。但在连接时,发现没有与函数声明相一致的函数定义,结果产生“不能确定的外部函数”的连接错误。
函数返回在声明时约定数据类型。例如:
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
例中,函数返回的变量a或b是int型的。
如果返回的是其他基本数据类型,则在返回时,先作隐含的类型转换,然后再返回。例 如,下面的代码中,主函数中的变量a被初始化为3:
int f()
{
return 3.5;
}
void main()
{
int a=f();
}
因为函数f()定义的返回类型是int,所以return语句的值3.5被转换成int型数3之后,返回给主函数,赋给了变量ao
如果函数返回的是不相容的数据类型(比如,后面介绍的类对象), 则函数将在编译时给出一个“不能将类转换成int"的错误。
函数的返回值也称函数值。返回的不是函数本身,而是一个值。
return语句后面的括号是任选的,例如,“return(3);”等价于“return 3;”。
return语句可用于改变执行顺序。例如:
int min(int a,int b)
{
if(a<b)
return a;
else
return b;
}
在这里,return语句还起到了改变计算顺序的作用。因为return是返回语句,它将退出函数体,所以该语句之后的语句不会被执行了:
无返回的函数也可以使用return,但不能返回值:例如:
void message(int a)
{
if(a>=0)
return;
//...
}
在这里,return语句起了一个改变语句顺序的作用。
在有返回类型的函数中,return后面所跟的表达式并不直接替换调用函数,而是先经过求值计算,必要的时候进行类型转换,然后将其存放到内存的某个区域:该区域视编译器的不同而不同,也视返回类型的不同而不同。例如,BC将一个返回整型的数存放在栈区(见5.4节)的位置。在存放到一个专用的区域后,再将其变量的地址传给调用函数,以使调用函数把它作为函数返回值:
编译器遇到一个函数调用时,需要判断该函数调用是否正确,该机制即函数原型。
->main()的返回值
main()是特殊的函数,它由操作系统调用,返回到操作系统。 函数头void main()是说,不返回任何值给操作系统,所以,在main()函数体的最后,无须“return 1;”之类的语句。如果函数头为int main()或main(),则函数体的最后必须给出“return 1;”之类的语句。
对于DOS操作系统来说,return 1和return 0都是无所谓的。
为了省略“return 1;” 这种无谓的操作,本书一律用void main()定义格式。