函数是编程里最重要的概念之一:把一段代码封装起来,起个名字,需要时调用。它让代码可复用、可读、好维护。本章讲如何定义函数、传参数、返回值。
6.1 为什么需要函数
假设要算很多次"两个数的平方和"a² + b²,每次都写:
intr1=3*3+4*4;intr2=5*5+6*6;intr3=7*7+8*8;又啰嗦又容易错。用函数封装:
intsquareSum(inta,intb){// 定义函数returna*a+b*b;}intr1=squareSum(3,4);// 调用:返回 25intr2=squareSum(5,6);// 61清爽多了。函数 = 一段有名字、可重复调用的代码。
6.2 定义函数
函数的完整结构:
返回类型 函数名(参数列表){// 函数体return返回值;}逐部分解释:
- 返回类型:函数算出来的结果是什么类型(
int、double、void…) - 函数名:调用时用的名字
- 参数列表:调用时传入的"输入"(可以有多个,用逗号分隔;也可以没有)
- 函数体:
{ }里要执行的代码 return:返回结果,并结束函数
举例:
// 无参数、无返回值的函数voidgreet(){std::cout<<"你好!"<<std::endl;}// 有参数、有返回值intadd(intx,inty){returnx+y;}// 有参数、无返回值voidprintTwice(intn){std::cout<<n<<" "<<n<<std::endl;}void表示"没有返回值",这样的函数不需要写return(或写return;)。- 参数就是"输入",返回值就是"输出"。
6.3 调用函数
定义好函数后,用函数名(实际参数)调用:
#include<iostream>intadd(intx,inty){returnx+y;}intmain(){intresult=add(3,5);// 调用 add,3 和 5 是"实参"std::cout<<result<<std::endl;// 8return0;}调用过程:
- 程序执行到
add(3, 5) - 跳进
add函数,x=3、y=5 - 执行
return x + y;,算出 8 - 带着 8 跳回调用处,
result = 8
术语:定义时写的是形参(
x、y),调用时传的是实参(3、5)。实参的值复制给形参。
6.4 参数的值传递
C++ 默认是值传递:调用函数时,把实参的值复制一份给形参。所以函数内修改形参,不影响外部的实参:
#include<iostream>voidchange(intx){x=100;// 改的是副本}intmain(){inta=5;change(a);std::cout<<a<<std::endl;// 还是 5,没被改}想真正修改外部的变量,要用引用(第 8 章讲)。
6.5 函数声明与定义分离
C++ 要求"先声明、后使用"。如果函数定义在main之后,main里就调用不到。解决方法是先声明:
#include<iostream>intadd(intx,inty);// 函数声明(也叫原型):只写签名,不写函数体intmain(){std::cout<<add(3,5)<<std::endl;// 现在可以调用了return0;}intadd(intx,inty){// 函数定义:在下面补全函数体returnx+y;}声明只告诉编译器"有这么个函数,长这样",定义才给出具体实现。真实项目里,声明通常放头文件(.h),定义放源文件(.cpp),后面会看到。
6.6 返回值 vs 打印:别搞混
新手常混淆"返回"和"打印":
intgetFive(){std::cout<<"5"<<std::endl;// 这是"打印",不是"返回"return5;// 这才是"返回"}- 打印(
std::cout)是给人看的,结果显示在屏幕。 - 返回(
return)是把值交给调用者,用于后续计算。
很多函数既要返回也要打印,但要清楚两者是两回事。
6.7 递归:函数调用自己
函数可以调用自己,这叫递归。经典例子是阶乘n! = n × (n-1) × ... × 1:
intfactorial(intn){if(n<=1)return1;// 基准情况:递归的出口returnn*factorial(n-1);// 递归调用自己}// factorial(5) = 5 * factorial(4) = 5 * 4 * factorial(3) = ... = 120递归必须有一个基准情况(停止条件),否则会无限调用导致崩溃。
递归虽然优雅,但初学不必强求。理解"函数能调用自己"即可。
6.8 完整示例
#include<iostream>// 判断一个数是否为质数boolisPrime(intn){if(n<2)returnfalse;// 小于 2 的不是质数for(inti=2;i*i<=n;i++){// 只需试除到 sqrt(n)if(n%i==0)returnfalse;// 能整除,不是质数}returntrue;}intmain(){std::cout<<"100 以内的质数:"<<std::endl;for(inti=1;i<=100;i++){if(isPrime(i)){std::cout<<i<<" ";}}std::cout<<std::endl;return0;}这个例子把"判断质数"封装成isPrime函数,主函数里就能干净地复用。
实际输出:
100 以内的质数: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 976.9 小结
- 函数 = 有名字、可复用的代码块。
- 定义:
返回类型 函数名(参数) { 函数体 }。 return返回结果;void表示无返回值。- 默认值传递:函数内改参数不影响外部。
- 先声明、后使用;声明和定义可以分离。
- 递归是函数调用自己,必须有停止条件。
下一章,学习数组与字符串——存储一组数据和文字。
练习题
- 写函数
max(a, b)返回两个数中较大的一个。 - 写函数
isEven(n)判断偶数,返回 bool。 - 写函数计算
1+2+...+n的和。 - 写递归函数求斐波那契数列第 n 项。
- 写函数
abs(x)返回绝对值,比较值传递的效果。