大家好,这里是彩妙呀~

从C语言过渡到C++,你会发现函数不再是简单的"输入-处理-输出"结构,而是拥有了更强大的表达能力。缺省参数让你可以为函数参数设置默认值,调用时无需提供所有参数;函数重载则允许同名函数处理不同类型的参数,大大提升了代码的可读性和灵活性。这两个特性看似简单,却深刻改变了C++的编程方式------不再需要为相似功能创建不同名称的函数,而是让函数本身"理解"上下文。
理解它们的使用规则和最佳实践,是掌握C++面向对象编程的重要一步,也是你从C语言思维转向C++思维的关键转折点
目录
缺省参数
什么是缺省参数?
**缺省参数(Default Arguments)**是函数声明或定义时为参数指定的默认值。当调用函数时,若未显式传递对应实参,则自动采用该默认值。
cpp
#include <iostream>
#include <string>
using namespace std;
//下面就给大家展示什么是缺省函数
void put_string(string name = "name" , string message = "Welcome back!")
{
cout << "Hello, " << name << "!" << message << endl;
}
int main(){
put_string();
put_string("小明");
put_string("小红","你好啊");
return 0;
}

这里使用的是线上编译器:C++ 在线工具 | 菜鸟工具 (jyshare.com),大家如果有c++程序,可以在这个网站上快速运行。
运行代码后,我们可以看出:我们定义的缺省函数,在你使用他时,如果没有传递他所需的参数时,编译器会使用在其定义中的默认值:name 以及 welcome back。
使用规则与限制
缺省函数的声明分为三类:
cpp
// 声明
//第一类:无缺省函数
void fullDefault1(int a, int b, int c);
//第二类:半缺省函数
void fullDefault2(int a, int b = 2, int c = 3);
//第三类: 全缺省函数:所有参数都有默认值
void fullDefault3(int a = 1, int b = 2, int c = 3);
//第四类:声明与定义分离 头文件(.h)中:
// 声明:指定默认值
void func3(int a = 1, int b = 2);
// 定义:不指定默认值
void func3(int a, int b) {
// 函数体
}
// 使用示例
void fullDefault(int a = 1, int b = 2, int c = 3);
fullDefault(); // 全缺省:a=1, b=2, c=3
fullDefault(10); // a=10, b=2, c=3
fullDefault(10, 20); // a=10, b=20, c=3
**缺省参数的声明位置:**缺省函数在声明时如果使用了默认值,那么定义时不可以再写默认值:
cpp
// 声明(头文件或函数前)
void func(int a = 10);
// 定义(不可再写默认值)
void func(int a) {
/* ... */
}
默认值的类型:必须是全局变量或常量表达式。
参数顺序要求 :必须从右往左连续设置默认值,不能跳过。
cpp
// 正确:
void func(int a, int b = 20, int c = 30);
// 错误:
void func(int a = 10, int b, int c = 30);
C++要求默认参数必须从右向左连续设置,是为了避免函数调用时产生歧义。
例如,若允许
void func(int a=0, int b, int c),则调用func(2, 3)时,编译器无法确定是a=2, b=3还是a=0, b=2, c=3。这种设计确保了参数解析的明确性,避免了歧义。
函数重载
函数重载(Function Overloading) 允许在同一作用域内定义多个同名函数 ,但这些函数的参数列表(参数类型、数量或顺序)必须不同。在c语言中,并不支持函数重载,这个技术的引用实在c++中才实现的。
cpp
#include <iostream>
using namespace std;
// 参数类型不同
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
// 参数数量不同
void print() { cout << "No arguments" << endl; }
void print(string s) { cout << "String: " << s << endl; }
// 参数顺序不同
int subtract(int a, double b) { return a - (int)b; }
int subtract(double a, int b) { return (int)a - b; }
int main() {
cout << add(3, 4) << endl; // 调用 int add(int, int)
cout << add(3.5, 4.2) << endl; // 调用 double add(double, double)
print(); // 输出: No arguments
print("Hello"); // 输出: String: Hello
cout << subtract(10, 2.5) << endl; // 调用 subtract(int, double)
}
编译器如何区分重载函数?
C++通过**名称修饰(Name Mangling)**为每个重载函数生成唯一的符号。例如:
add(int, int)可能被修饰为_Z3addiiadd(double, double)可能被修饰为_Z3adddd链接时,编译器根据调用时的参数类型匹配正确的函数地址。
**注意:**在函数重载时,不可以只能修改返回值!
cpp
// 错误:仅返回值不同无法重载
int parse();
double parse(); // ❌ 无法区分
这是因为在编译器调用这类函数时,不可以分辨出你要调用的是哪一种函数:即存在调用歧义。
同样的,当缺省参数遇到函数重载,就像两个相似的函数容易混淆:也会存在调用歧义
cpp
// 危险组合!可能导致歧义
void print(int a, int b = 10);
void print(int a);
print(5); // ❓编译器无法确定该调用哪个函数
print(5, 10); // 明确调第一个参数版本
这两类时我们初学时要注意的地方,只需多加注意,即可避免。
总结:选择合适的设计模式
| 特性 | 使用场景 | 优点 | 注意事项 |
|---|---|---|---|
| 缺省参数 | 常见配置项、兼容性升级 | 减少重复代码 | 不能跳过参数设置 |
| 函数重载 | 类型转换、操作符扩展 | 统一接口设计 | 返回值不能区分重载 |
最佳实践建议:
- 对于简单接口优先使用缺省参数(如
void init(int size = 100)) - 对于需要处理多种数据类型的场景使用重载(如
bool compare(T a, U b)) - 避免过度重载导致函数职责不清
在彩妙其他博客中,如果使用到这些函数时,也会给大家讲解一下其函数在代码中的作用。
只需多加练习,这两类函数就可以手到擒来啦