在编程中,我们经常遇到这样的情况:某个函数参数在大多数情况下都使用相同的值,但偶尔也需要改变。如果每次调用都要显式传入这个"常用值",不仅显得冗余,还可能让代码变得臃肿。C++ 的默认参数正是为了解决这个问题而设计的------它允许我们在函数声明或定义时为参数指定默认值,这样在调用时就可以省略这些参数,编译器会自动用默认值填充。
今天,我们就通过几个简单的代码示例,来彻底搞懂 C++ 中默认参数的用法和需要注意的规则。
1. 没有默认参数的函数
先来看一个最基础的加法函数,它有三个参数,调用时必须全部传入:
cpp
#include <iostream>
using namespace std;
int Add(int a, int b, int c)
{
return a + b + c;
}
int main()
{
int a = 10;
cout << "Add(10,20,30)=" << Add(10, 20, 30) << endl;
return 0;
}
输出:
Add(10,20,30)=60
这段代码很好理解:Add 函数需要三个 int 参数,调用时我们给了 10、20、30,计算结果并输出。
如果某个参数(比如 b 或 c)在大多数情况下都是固定的,每次都要写就显得有点啰嗦。这时就可以用默认参数来简化。
2. 引入默认参数
我们给后两个参数加上默认值:
cpp
#include <iostream>
using namespace std;
int Add(int a, int b = 20, int c = 30)
{
return a + b + c;
}
int main()
{
int a = 10;
cout << "Add=" << Add(10) << endl;
return 0;
}
输出:
text
Add=60
这里,b 和 c 分别有了默认值 20 和 30。调用 Add(10) 时,编译器自动将 10 赋给 a,然后 b 和 c 使用默认值,最终结果依然是 60。
当然,你也可以覆盖默认值,比如 Add(10, 30, 40) 会得到 80,完全灵活。
3. 默认参数的规则一:从右向左连续设置
默认参数有一个非常重要的规则:一旦某个参数开始设置默认值,它右侧的所有参数都必须设置默认值。换句话说,默认参数必须从参数列表的右边开始连续定义。
看下面这个错误的例子(代码中已注释掉):
cpp
// int Add(int a, int b = 20, int c) // 错误!
// {
// return a + b + c;
// }
为什么错?因为 b 设置了默认值,但右侧的 c 却没有默认值。这会导致调用时产生歧义:如果我只传两个参数,编译器该把第二个参数赋给 b 还是 c?
正确的做法是:如果要给 b 默认值,那么 c 也必须给默认值;或者从最右边开始给默认值,例如 int Add(int a, int b, int c = 30) 是合法的。
所以,规则一总结为:默认参数必须从参数列表的右端向左连续出现。
4. 默认参数的规则二:声明和定义只能一处指定默认值
在实际开发中,我们通常会把函数声明放在头文件,定义放在源文件。这时要注意:函数的声明和定义中,只能有一处为参数指定默认参数,否则编译器会报"重复定义默认参数"的错误。
例如,下面的代码是正确的(默认参数只在定义中给出):
cpp
#include <iostream>
using namespace std;
// 声明中不指定默认参数
int Add(int a, int b, int c);
// 定义中指定默认参数
int Add(int a, int b = 20, int c = 30)
{
return a + b + c;
}
int main()
{
int a = 10;
cout << "Add=" << Add(10) << endl;
return 0;
}
输出仍然是 60。
但如果你同时在声明和定义中都写了默认参数(哪怕值一样),就会引发编译错误。
一般建议将默认参数写在声明中,这样调用者(通过头文件)能看到默认值,而定义中不再重复写默认值,保持代码清晰。
总结
通过这几个简单的例子,我们掌握了 C++ 默认参数的核心用法和两个重要规则:
-
默认参数让函数调用更简洁,尤其适用于参数常用值固定的情况。
-
规则一:默认参数必须从右向左连续设置,不能跳跃。
-
规则二:函数声明和定义中只能有一处指定默认参数(通常放在声明中)。