1.函数及其定义
一个典型的函数定义包括以下部分:返回类型、函数名字、由0个或者多个形参组成的列表、函数体。其中,形参以逗号隔开,形参列表位于一对圆括号内。
如下所示:
返回值类型 函数名字(形参类型 形参0,形参类型 形参1,...)
{
函数体;
}
//例如
int sumfun(int ia, int ib)
{
int ic = ia + ib;
return ic;
}
这里的sumfun就是函数名,sumfun作用于两个整型的参数,并且返回一个整形值,其功能就是返回一个ic的数值。
2. 调用函数
我们一般用 函数名(实参列表) 的方式调用函数。
官方一点说,通过 调用运算符 来执行函数,调用运算符是一对圆括号,它作用于一个表达式,该表达式是函数或者指向函数的指针;圆括号之内是一个用逗号隔开的实参列表,我们用实参初始化函数的形参。调用表达式的类型就是函数的返回类型。
(选自电子工业出版《C++Primer》第5版 P182)
函数的调用会完成两项工作:
一是实参初始化函数对应的形参;
二是将控制权转移给被调用函数。
当遇到return语句时函数结束执行过程,也会执行两项工作:
一是返回return中的值;
二是将控制权从被调函数转移回主调函数。
如果学习过单片机中断的同学,应该很好理解。只不过在C++这些过程中,可能会包含隐式的初始化,一般来说,在相对复杂的结构时,为了避免初始化消耗的时间和内存,可能会采用const引用或者引用的方式来进行实参的给定。
3.形参和实参
在函数调用的过程中,实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推。函数有几个形参,我们在调用时就必须提供相同数量的实参。
另外,提供的实参的类型 也必须和 函数形参的类型 相同。如果类型可以进行转换也是可以调用成功的,只不过可能会出现一些报警提示。
比如
sumfun(1,2);
sumfun(1.2 3.4); //正确,double转int但是可能会数据丢失
sumfun('a','c'); //错误,实参类型不匹配
sumfun(1); //错误,实参太少
sumfun(1,2,3); //错误,实参过多
我们可以测试一下sumfun(1.2 3.4)的结果:
int main()
{
int r = sumfun(1.2,3.4);
cout << r << endl;
return 0;
}
实际的结果其实是4,虽然1.2+3.4=4.6,而按照四舍五入的double转int规则,应该是5。但是实际上,在调用函数时,将两个实参1.2、3.4给int ia 和int ib的时候,就已经发生了转换,因此实际上初始化以后的形参ia、ib就是1和3了,另外在函数调用结束以后,ia和ib是会消亡的。
4.函数的形参列表
函数的形参列表可以为空,即调用时不需要给参数。但是不能省略,必须保留(),一般没有形参的函数可以按如下方式定义:
//隐式的定义没有形参的函数 void fun() { *****//函数体 } //显式的定义 void fun(void) { *****//函数体 }
另外,函数的形参都必须声明其类型,不能一个类型声明很多同类型的变量:
int fun1(int i1, i2) //错误,i2没有声明类型 int fun1(int i1, int i2) //正确
5.函数的返回类型
大多数类型都可以作为函数的返回类型,比较特殊的是 void,它表示函数不返回任何值。函数的返回类型不能是数组类型或者函数类型,但是可以是指向数组或者函数的指针。