【C++】C++核心语法:函数重载与缺省参数原理与避坑

📌 相关专栏

很高兴你点开这篇文章✨

这里会持续更新我喜欢的内容,关注我,一起慢慢变好呀

👍 点赞 ⭐ 收藏 💬 评论


文章目录

  • 一、前言
  • 二、缺省参数(默认参数)
    • [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)

缺省参数的规则(非常重要)

  1. 必须从右往左连续给出

    • 正确:void Func(int a, int b=10, int c=20)
    • 错误:void Func(int a=10, int b, int c=20)
  2. 传参从左往右连续匹配,不能跳过

    cpp 复制代码
    Func1(1, 2);    // a=1, b=2, c=30(缺省)
    Func1(1);       // a=1, b=20, c=30
    // Func1(, 2);  //  错误,不能跳过一个参数
  3. 半缺省函数不能"传空"

    cpp 复制代码
    Func2(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 调用规则(匹配优先级)

🐾 编译器按以下顺序找匹配的函数:

  1. 精确匹配(参数类型完全一致)
  2. 隐式类型转换匹配(如 int → double)
  3. 报错(找不到或二义性)
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++中的使用)

谢谢你看到这里呀

如果喜欢这篇内容,点个关注,下次更新不迷路✨

👍 点赞 ⭐ 收藏 💬 评论

相关推荐
段一凡-华北理工大学2 小时前
工业领域的Hadoop架构学习~系列文章03:MapReduce编程模型深度解读
大数据·人工智能·hadoop·学习·架构·高炉炼铁·高炉智能化
DreamLife☼2 小时前
OpenBCI-Python与OpenBCI:实时脑电信号采集实战
开发语言·python·硬件·选型·openbci·cyton·ganglion
李子琪。2 小时前
Web 漏洞与防御机制实验报告
前端·经验分享
AI行业学习2 小时前
CC-Switch 下载、安装与使用配置指南【2026.5.29】
java·开发语言·vscode·python·eclipse·laravel
许彰午2 小时前
03_Java流程控制详解
java·开发语言·python
fpcc2 小时前
C++编程实践——提高缓存的命中
c++·缓存
元气少女小圆丶2 小时前
SenseGlove Nova 2+Unity开发笔记3
笔记·unity·游戏引擎
meowrain2 小时前
Git HTTPS Token 凭据配置指南
git·网络协议·https
SoftLipaRZC2 小时前
C语言内存函数完全指南:memcpy/memmove/memset/memcmp
c语言·开发语言