为何需要函数
函数让您能够划分和组织程序的执行逻辑。通过使用函数,可将应用程序的内容划分成依次调用的逻辑块。
函数原型
下面函数原型函数原型指出了函数的名称( Area)、函数接受的参数列表(一个名为 radius 的 double 参数)以及返回值的类型( double)。
函数的定义
函数定义总是由一个语句块组成。除非返回类型被声明为 void,否则函数必须包含一条 return 语句。
int function(int num)
{
num *= num;
return num;
}
函数调用的实参
如果函数声明中包含形参,调用函数时必须提供实参,它们是函数的形参列表要求的值。
int num = 10;
cout << "function(num) = " << function(num) << endl;
带默认值的函数参数
对调用者来说,这个参数是可选的,因此仍可使用下面的语法来调用函数 Area(),就像第二个参数不存在一样:
double Area(double radius, double pi = 3.14)
{
return pi * radius * radius;
}
int main()
{
int radius = 10;
cout << "Area(radius) = " << Area(radius) << endl;
cout << "Area(radius, 3.1415926) = " << Area(radius, 3.1415926) << endl;
return 0;
}
输出为:
Area(radius) = 314
Area(radius, 3.1415926) = 314.159
递归函数
函数调用它自己,这样的函数称为递归函数。递归函数必须有明确的退出条件,满足这种条件后,函数将返回,而不再调用自己。(递归太深容易引发栈溢出)
int GetFibNumber(int fibIndex)
{
if (fibIndex < 2)
return fibIndex;
else
return GetFibNumber(fibIndex - 1) + GetFibNumber(fibIndex - 2);
}
int main()
{
cout << "Enter 0-based index of desired Fibonacci Number: ";
int index = 0;
cin >> index;
cout << "Fibonacci number is: " << GetFibNumber(index) << endl;
return 0;
}
使用函数处理不同的数据类型
重载函数
名称和返回类型相同,但参数不同的函数被称为重载函数。
#define pi 3.1415926
// 计算圆的面积
double Area(double radius)
{
return pi * radius * radius;
}
// 计算圆柱体的面积
double Area(double radius, double height)
{
return pi * radius * radius + height * 2 * pi * radius;
}
int main()
{
int radius, height;
cout << "radius is :";
cin >> radius;
cout << "height is :";
cin >> height;
cout << "Area(radius) = " << Area(radius) << endl;
cout << "Area(radius, height) = " << Area(radius, height) << endl;
return 0;
}
输入输出为:
radius is :10
height is :10
Area(radius) = 314.159
Area(radius, height) = 942.478
将数组传给函数
void DisplayArray(int num[], int len)
{
for (int s = 0; s < len; s++)
cout << num[s];
cout << endl;
}
void DisplayArray(char str[], int len)
{
for (int s = 0; s < len; s++)
cout << str[s];
cout << endl;
}
int main()
{
int numBuf[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
char strBuf[5] = {'h', 'e', 'l', 'l', 'o'};
DisplayArray(numBuf, 10);
DisplayArray(strBuf, 5);
return 0;
}
输出为:
1234567890
hello
微处理器如何处理函数调用
函数调用意味着微处理器跳转到属于被调用函数的下一条指令处执行。执行完函数的指令后,将返回最初离开的地方。为了实现这种逻辑,编译器将函数调用转换为一条供微处理器执行的 CALL指令,该指令指出了接下来要获取的指令所在的地址,该地址归函数所有。遇到 CALL 指令时,微处理器将调用函数后将要执行的指令的位置保存到栈中,再跳转到 CALL 指令包含的内存单元处。
内联函数
常规函数调用被转换为 CALL 指令,这会导致栈操作、微处理器跳转到函数处执行等。相对于实际执行 GetPi( )所需的时间,执行函数调用的开销可能非常高。
double GetPi(void)
{
return 3.1415926;
}
使用关键字 inline 发出请求,要求在函数被调用时就地展开它们,提高代码的执行速度。
inline double GetPi(void)
{
return 3.1415926;
}
将函数声明为内联的会导致代码急剧膨胀,在声明为内联的函数做了大量复杂处理时尤其如此。应尽可能少用关键字 inline,仅当函数非常简单,需要降低其开销时,才应使用该关键字。
自动推断返回类型
#define pi 3.1415926
// 计算圆的面积
auto Area(double radius)
{
return pi * radius * radius;
}
int main()
{
int radius;
cout << "radius is :";
cin >> radius;
cout << "Area(radius) = " << Area(radius) << endl;
return 0;
}