一、带默认形参值的函数的概念
在定义或声明函数时,可以为形参预先指定一个默认值。当函数被调用时,如果调用者给出了对应位置的实参,则用实参初始化形参;如果没有给出实参,则形参自动采用预先声明的默认值。
这一特性可以减少函数调用的参数书写量,使代码更简洁灵活。
二、默认形参值的语法
返回类型 函数名(形参1, 形参2 = 默认值2, 形参3 = 默认值3, ...)
{
语句序列
}
示例:
int Add(int z, int x = 3, int y = 5)
{
return x + y;
}Code language: JavaScript (javascript)
调用方式:
Add(1, 2, 3); // 实参全部给出,x=2, y=3, 返回 5
Add(1, 2); // 只给出前两个实参,y 使用默认值 5,返回 7
Add(2); // 只给出第一个实参,x 使用默认值 3,y 使用默认值 5,返回 8Code language: JavaScript (javascript)
三、默认形参值的排列规则
有默认值的形参必须位于形参列表的最右侧。 也就是说,在有默认值的形参右边,不能出现无默认值的形参。
// 正确
int func(int a, int b = 2, int c = 3);
// 错误
int func(int a = 1, int b, int c = 3); // b 没有默认值,但在有默认值的 a 右边Code language: JavaScript (javascript)
原因:函数调用时实参按位置从左到右依次匹配形参。如果允许中间有默认值而右侧没有,编译器无法确定实参应该匹配哪个形参。
四、默认形参值的作用域与重复定义规则
1. 在相同作用域内,不允许对同一个函数的同一个形参的默认值重复定义
即使前后两次指定的默认值完全相同,也不允许。
// 错误示例
int Add(int z, int x = 3, int y = 5); // 第一次声明,指定了默认值
int main()
{
Add(1, 2, 3);
cout << Add(1, 2) << endl;
cout << Add(2) << endl;
cout << Add(5) << endl;
return 0;
}
int Add(int z, int x = 3, int y = 5) // 错误:重复定义默认值
{
return x + y;
}Code language: JavaScript (javascript)
2. 正确做法:只在声明中指定默认值,定义中不指定
// 函数原型声明(通常在头文件或文件开头)
int Add(int z, int x = 3, int y = 5);
int main()
{
Add(1, 2, 3);
cout << Add(1, 2) << endl; // 输出 7
cout << Add(2) << endl; // 输出 7
cout << Add(5) << endl; // 输出 8
return 0;
}
// 函数定义(在 main 之后)
int Add(int z, int x /*=3*/, int y /*=5*/)
{
return x + y;
}Code language: JavaScript (javascript)
注意:定义处的 /*=3*/ 和 /*=5*/ 是注释,不是默认值。默认值只在声明中指定一次即可。
五、代码示例
以下代码演示了带默认形参值的函数的多种应用场景:
#include <iostream>
#include <string>
using namespace std;
// 示例1:基本默认值
void printInfo(string name, int age = 18, string city = "北京")
{
cout << "姓名:" << name << ",年龄:" << age << ",城市:" << city << endl;
}
// 示例2:计算体积(长、宽、高,后两个有默认值)
int volume(int length, int width = 1, int height = 1)
{
return length * width * height;
}
// 示例3:带默认值的引用传递
void increment(int &x, int step = 1)
{
x += step;
}
// 示例4:多个参数,部分有默认值
double calculate(double price, double discount = 0.0, double tax = 0.13)
{
return price * (1 - discount) * (1 + tax);
}
// 示例5:函数声明在前,定义在后
int power(int base, int exp = 2);
int main()
{
// 测试 printInfo
printInfo("张三"); // 使用 age=18, city="北京"
printInfo("李四", 25); // 使用 city="北京"
printInfo("王五", 30, "上海"); // 全部使用实参
cout << endl;
// 测试 volume
cout << "volume(10) = " << volume(10) << endl; // 10 * 1 * 1 = 10
cout << "volume(10, 5) = " << volume(10, 5) << endl; // 10 * 5 * 1 = 50
cout << "volume(10, 5, 2) = " << volume(10, 5, 2) << endl; // 10 * 5 * 2 = 100
cout << endl;
// 测试 increment
int num = 10;
cout << "num = " << num << endl;
increment(num); // step 使用默认值 1
cout << "increment(num) 后 num = " << num << endl;
increment(num, 5); // step = 5
cout << "increment(num, 5) 后 num = " << num << endl;
cout << endl;
// 测试 calculate
cout << "calculate(100) = " << calculate(100) << endl;
cout << "calculate(100, 0.2) = " << calculate(100, 0.2) << endl;
cout << "calculate(100, 0.2, 0.05) = " << calculate(100, 0.2, 0.05) << endl;
cout << endl;
// 测试 power
cout << "power(3) = " << power(3) << endl; // 3^2 = 9
cout << "power(3, 3) = " << power(3, 3) << endl; // 3^3 = 27
return 0;
}
// power 函数定义
int power(int base, int exp)
{
int result = 1;
for (int i = 0; i < exp; i++)
{
result *= base;
}
return result;
}Code language: PHP (php)
七、常见错误
1. 默认形参不在最右侧
int func(int a = 1, int b, int c = 3); // 错误:b 没有默认值Code language: JavaScript (javascript)
2. 重复指定默认值
int foo(int x = 5);
int foo(int x = 5); // 错误:重复定义默认值Code language: JavaScript (javascript)
3. 调用时试图跳过前面的参数
void bar(int a, int b = 2, int c = 3);
bar(1, , 5); // 错误:不能跳过 b 直接给 c 传值Code language: JavaScript (javascript)
正确写法:bar(1, 2, 5); 或 bar(1);(b 和 c 都用默认值)
4. 默认形参与函数重载产生二义性
int add(int a, int b = 10);
int add(int a);
add(5); // 二义性:调用哪个?add(int, int) 还是 add(int)?Code language: JavaScript (javascript)
5. 在函数定义中重复指定默认值
int func(int x = 5);
int func(int x = 5) { return x; } // 错误:重复指定Code language: JavaScript (javascript)
正确做法:声明中指定,定义中不指定。