C++函数的定义与声明
困难83把重复代码打包成积木:C++函数的定义与声明
同学们,写程序时经常会遇到“同样的事要做很多次”的情况。比如,要计算3的平方、8的平方、15的平方……每次都得写 3*3、8*8、15*15,既麻烦又容易写错。C++里有一种很聪明的办法——函数。它就像一块万能小积木,你把要做的事情提前做好,后面随时可以把它“搭”到程序里,只需要给积木不同的数据,它就能帮你算出结果。
函数不仅能让程序变短,还能让你的代码像搭乐高一样模块化:每一块积木负责一个独立的功能,出了问题只需要检查那块积木,其他部分不用动。
1. 函数是什么?——像“调料包”一样方便
想象一下,你在学校食堂吃面条,每次都想要加一点辣椒油。如果食堂阿姨把辣椒油放在一个大桶里,每次都要用勺子舀,很慢。更好的办法是:提前把辣椒油装成一个个小包(调料包)。想吃的时候,撕开一包倒进去就完了。
函数就是这样的“调料包”。它把一段能完成特定任务的代码包装起来,起一个名字(比如 add、square)。以后你需要执行这个任务时,只需要“叫”它的名字,再给它一些必要的原料(参数),它就会自动完成工作,并把结果(返回值)还给你。
2. 如何制作一块“积木”——函数的定义
要制作一块积木,你需要告诉C++四件事:
- 返回值类型:积木做完事之后,要给你一个什么东西?是整数(
int)、小数(double)还是什么都不给(void)? - 函数名:积木的名字,比如
square、maxNum,要让人一看就懂。 - 参数列表:积木需要你提供哪些原料?写在括号里,每个原料都要说明类型和名字。
- 函数体:积木具体怎么做事的代码,放在花括号
{}里。
下面是一个计算任意整数平方的函数定义:
int square(int x) { // 返回整数类型,函数名叫square,需要一个整数参数x
return x * x; // 计算x*x并返回结果
}
如果你想计算两个数中的最大值,可以再做一个积木:
int maxNum(int a, int b) { // 返回整数,需要两个整数a和b
if (a > b) {
return a; // 如果a大就返回a
} else {
return b; // 否则返回b
}
}
生活例子:你有一个零钱罐,里面有很多1元、5角、1角的硬币。你想知道一共有多少钱(单位是角)。你可以写一个函数 calcTotal,它接收三种硬币的数量,返回总钱数(角)。这样每次你数完硬币,只要调用这个函数,输入数字,就能立刻得到总钱数,不用自己加来加去。
3. 给积木贴一张“标签”——函数的声明
有时候,你的积木定义在程序中比较靠后的位置,但前面的代码想提前使用它。怎么办?你可以在程序最开始的地方贴一张“标签”,告诉C++:“我这里有这么一块积木,名叫square,它需要一个整数,返回一个整数,具体做法在后面写。”这个标签就是函数声明。
声明很像函数的“抬头”,但不写具体怎么实现(没有花括号),只写返回类型、函数名和参数,最后跟一个分号。
int square(int x); // 声明:我说有这个函数,但具体怎么做在后面再写
在大型项目里,声明通常放在文件开头或者一个单独的头文件(.h 文件)里,这样程序里所有地方都能知道这块积木的存在。定义则放在另一个文件(.cpp 文件)里,实现具体功能。
声明只负责“说”(告诉编译器有这个函数),定义负责“做”(实际写出代码)。
如果没有定义就调用函数,编译器会报错“未定义的引用”,就像你找同学借一本《哈利·波特》,他说“我有这本书”,结果你去找时,发现他根本就没有书,你会很生气。
4. 新手容易掉进的“坑”
-
忘记写返回值:函数有返回类型(比如
int),就必须在函数体里写return。否则程序不知道要给你什么结果。
❌ 错误:int plusOne(int x) { x + 1; // 没写return,编译器会报错 }✅ 正确:
int plusOne(int x) { return x + 1; // 返回结果 } -
参数数量或类型不对:定义时写明了要两个
double,调用时却只给一个整数,或者给了三个整数,编译器会报错“没有匹配的函数”。 -
声明和定义不一致:比如声明里参数是
int,定义里却变成double,编译器会认为它们是两个不同的函数,导致莫名其妙的问题。 -
忘记写分号:声明末尾一定要有分号
;,定义的花括号后面不用分号。
5. 完整示例:用函数计算圆的面积和周长
下面是一个完整的程序,包含函数的声明、定义和调用。注意看代码中的中文注释,帮你理解每一行在干什么。
#include <iostream>
using namespace std;
// 函数的声明(贴在前面,告诉编译器有两个函数要用)
double circleArea(double r); // 计算圆面积,参数r是半径,返回double
double circlePerimeter(double r); // 计算圆周长
int main() {
double radius; // 半径
cout << "请输入圆的半径:";
cin >> radius;
double area = circleArea(radius); // 调用函数,把radius传进去,得到面积
double perimeter = circlePerimeter(radius); // 调用函数,得到周长
cout << "面积 = " << area << endl;
cout << "周长 = " << perimeter << endl;
return 0;
}
// 函数的定义(实现具体功能)
double circleArea(double r) { // 返回类型double,参数r
const double pi = 3.1415926; // 圆周率常量
return pi * r * r; // 圆的面积公式
}
double circlePerimeter(double r) { // 返回类型double,参数r
const double pi = 3.1415926;
return 2 * pi * r; // 圆的周长公式
}
你可以试着输入不同的半径,程序会正确输出面积和周长。如果想把函数定义直接写在 main 前面,那就不需要声明了,因为定义本身就包含了声明的作用。
6. 接下来还可以学什么?
函数是C++里最重要的积木块之一。掌握了它之后,还可以继续探索:
- 函数重载:同一个函数名,可以有不同的参数版本(比如一个
sum函数既能加两个整数,也能加三个整数)。 - 递归:函数自己调用自己,解决像“爬楼梯”、“阶乘”这类问题。
- 默认参数:给参数设一个默认值,调用时可以少写一个参数。
- 头文件与多文件编程:把声明放在
.h文件,定义放在.cpp文件,让代码组织更清晰。
现在,去试试自己写几个小函数吧!比如计算考试平均分、判断一个数是不是质数,或者模拟一个简易计算器。每写一个函数,你就搭起了一块属于自己的编程积木。
例题精讲
关于C++中函数的声明与定义,以下说法正确的是?
在C++中,如果函数定义出现在函数调用之后,必须在调用前先声明该函数。
补全以下函数定义,使其与函数声明匹配,功能为计算两个整数的差并返回。\n函数声明:int subtract(int a, int b);\n函数定义:___ subtract(int a, int b) { ___ a - b; }关于C++函数的默认参数,下列哪项描述是正确的?
下列代码试图通过函数重载实现打印不同类型数据的功能,请补全函数定义。\n函数声明(重载):\nvoid print(int x);\nvoid print(double y);\n函数定义(第一个):void print(int x) { cout << "Integer: " << x << endl; }\n函数定义(第二个):___ print(___ y) { cout << "Double: " << y << endl; }