📌 相关专栏
很高兴你点开这篇文章✨
这里会持续更新我喜欢的内容,关注我,一起慢慢变好呀
👍 点赞 ⭐ 收藏 💬 评论
文章目录
- 一、前言
- 二、缺省参数(默认参数)
-
- [2.1 什么是缺省参数?](#2.1 什么是缺省参数?)
- [2.2 全缺省 vs 半缺省](#2.2 全缺省 vs 半缺省)
- [2.4 缺省参数的典型应用场景:顺序表初始化](#2.4 缺省参数的典型应用场景:顺序表初始化)
- 三、函数重载
-
- [3.1 什么是函数重载?](#3.1 什么是函数重载?)
- [3.2 编译器如何区分重载函数?](#3.2 编译器如何区分重载函数?)
- [3.3 调用规则(匹配优先级)](#3.3 调用规则(匹配优先级))
- 四、总结
- 五、本文全部代码
一、前言
为什么需要缺省参数和函数重载?
🐾 在C语言中,你可能遇到过这些问题:
- 想给函数一个"默认行为",但必须每次传参
- 想写同名的函数(比如Add支持int和double),但C不允许
C++通过缺省参数和函数重载解决了这两个痛点。
本文的代码示例的是一个顺序表(SeqList)项目,我们边看代码边学。
二、缺省参数(默认参数)
2.1 什么是缺省参数?
为缺省参数就是在声明函数时给形参一个默认值。
- 调用时如果不传参,就用默认值;
- 传参了,就用传入的值。
cpp
void func(int a = 0)
{
cout << a << endl;
}
func(10); // 输出 10
func(); // 输出 0(缺省值)
2.2 全缺省 vs 半缺省
| 类型 | 含义 | 示例 |
|---|---|---|
| 全缺省 | 所有形参都有缺省值 | void Func1(int a=10, int b=20, int c=30) |
| 半缺省 | 部分形参有缺省值 | void Func2(int b, int c=30, int a=10) |
缺省参数的规则(非常重要)
-
必须从右往左连续给出
- 正确:
void Func(int a, int b=10, int c=20) - 错误:
void Func(int a=10, int b, int c=20)
- 正确:
-
传参从左往右连续匹配,不能跳过
cppFunc1(1, 2); // a=1, b=2, c=30(缺省) Func1(1); // a=1, b=20, c=30 // Func1(, 2); // 错误,不能跳过一个参数 -
半缺省函数不能"传空"
cppFunc2(1); // 可以 // Func2(); // 错误,第一个参数没有缺省值
2.4 缺省参数的典型应用场景:顺序表初始化
cpp
void SLInit(SL* pls, int n = 4);//int n=4:默认参数,指定容量为4(若调用时不传入---设新的内存容量,则自动使用4)
- 如果调用
SLInit(&s, 10)→ 预分配 10 个空间 - 如果调用
SLInit(&s)→ 使用缺省值 4 个空间
好处:用户不关心容量时用默认值,关心时可以自定义。
🐶 🐾 ✨ 🐾 🐶
三、函数重载
3.1 什么是函数重载?
同一个作用域内,函数名相同,但参数列表不同(类型、个数、顺序),编译器会自动选择匹配的函数执行。
cpp
// 参数类型不同,名字都叫Add
int Add(int left, int right);
double Add(double left, double right);
// 参数个数不同,名字都叫c
void c();
void c(int a);
// 参数顺序不同,名字都叫c
void c(char b, int q);
void c(int b, char q);
🐶 🐾 ✨ 🐾 🐶
3.2 编译器如何区分重载函数?
C++ 编译器会对函数名进行名字修饰(Name Mangling),把参数信息编码进函数名中。
例如:
- Add(int,int) → 可能被修饰为
_Add_int_int - Add(double,double) → 可能被修饰为
_Add_double_double
🐾 所以底层它们是不同的符号,不会冲突。
3.3 调用规则(匹配优先级)
🐾 编译器按以下顺序找匹配的函数:
- 精确匹配(参数类型完全一致)
- 隐式类型转换匹配(如 int → double)
- 报错(找不到或二义性)
cpp
Add(1, 2); // 匹配 int Add(int, int)
Add(1.1, 2.2); // 匹配 double Add(double, double)
c(10, 'a'); // 匹配 c(int, char)
c('a', 10); // 匹配 c(char, int)
// c(10, 10); // ❌ 两个int,c中没有没有匹配的函数,报错
🐾 编译器按以下顺序找匹配的函数:
cpp
void c1() {}
void c1(int a = 10) {}
c1(); // ❌ 二义性错误:编译器不知道该调用哪一个
**💡 结论:**不要同时使用缺省参数和函数重载制造二义性。
四、总结
| 特性 | 核心规则 | 常见坑 |
|---|---|---|
| 缺省参数 | 从右往左连续给,传参从左往右连续匹配 | 半缺省函数不能传空、不能跳过参数 |
| 函数重载 | 同名不同参(类型/个数/顺序) | 与缺省参数混用可能产生二义性 |
这两个特性是C++相比C的重要增强,也是我们接下来学习类和构造函数的基础(构造函数本质上就是带缺省参数的特殊函数)。
🐶 🐾 ✨ 🐾 🐶
五、本文全部代码
🐾 test.cpp
cpp
#define _crt_secure_no_warnings 1
//缺省函数(默认参数函数),说人话就是你不给我一个新的值,我就用原来的值(缺省值--->默认值)
#include<iostream>
using namespace std;
void func(int a = 0) //a的缺省值是0,func是用来测试的一个函数名
{
cout << a << endl;
}
//全缺省----所有变量(形参)都有缺省值
void func1(int a = 10, int b = 20, int c = 30) //a、b、c的缺省值分别是10、20、30
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl<<endl;
}
int main()
{
//传值是从左往右连续传的,不能跳过传下一个!
func1(1);//给一个实参
func1();//缺省值,保持原来的值
func1(1, 2, 3); //a=1,b=2,c=3
func1(1, 2); //a=1,b=2,c=30
func1(1); //a=1,b=20,c=30
func1(); //a=10,b=20,c=30
//不可以传空
//func1(1, ,3);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//半缺省(部分缺省)---有些变量(形参)没有缺省值,有些有
#include<iostream>
using namespace std;
//注意:形参给缺省值(默认值)时只能从右往左给->func2(int b, int c= 30, int a = 10)
// func2(int c= 30, int a = 10,int b )这个是错的
void func2(int b, int c= 30, int a =10)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl << endl;
}
int main()
{
//传值是从左往右连续传的,不能跳过传下一个!
func2(1);//给一个实参
//func2();//半缺省函数不可以传空
func2(1,2,3);
func2(1.2);
func2(1);
//func2();
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//函数重载----同名不同参
//函数重载就是"同名不同参",即编译器根据你传的参数类型、个数、顺序,
//自动帮你选最合适的那个函数去执行,输出对应函数的计算/打印结果,反之没有与之对应的就会报错
#include<iostream>
using namespace std;
//参数类型不同,名字都叫add
int add(int left, int right)
{
cout << "int add(int left, int right)" << endl;
return left + right;
}
double add(double left, double right)
{
cout << "double add(double left,double right)" << endl;
return left + right;
}
//参数个数不同,名字都叫c
void c()
{
cout << "c()" << endl;
}
void c(int a)
{
cout << "c(int a)" << endl;
}
//参数类型不同,名字都叫c、c1
void c(char b, int q)
{
cout << "c(char a,int b)" << endl;
}
void c(int b, char q)
{
cout << "c(int b,char a)" << endl;
}
void c1()
{
cout << "c()" << endl;
}
void c1(int a=10)
{
cout << "c(int a)" << endl;
}
int main()
{
//add(1, 2) : 1 和 2 都是 int 类型,
// 编译器精确匹配到 int add(int, int) ,执行 1+2=3
int a1=add(1, 2);
cout << a1 << endl;
//add(1.1, 2.2) : 1.1 和 2.2 都是 double 类型,
// 编译器精确匹配到 double add(double, double) ,执行 1.1+2.2=3.3
double a2=add(1.1, 2.2);
cout << a2 << endl;
c(); //无参数-》匹配c()
c(11); //一个int-》匹配c(int a)
c(10, 'a'); //先int后char-》匹配c(int char)
c('a', 10); //先char后int-》匹配c(char int)
//c(10,10); //两个int型,没有与之匹配的函数,报错
return 0;
}
🐶 🐾 ✨ 🐾 🐶
🐾 下一篇文章将讲解:
- 引用(什么是引用、引用传参、引用作为返回值)
- 顺序表的完整实现(初始化、尾插、查找、修改)
- 动态内存管理(malloc/realloc 在C++中的使用)

谢谢你看到这里呀
如果喜欢这篇内容,点个关注,下次更新不迷路✨
👍 点赞 ⭐ 收藏 💬 评论
