💓博主CSDN主页:杭电码农-NEO💓
⏩专栏分类:C++初阶之路⏪
🚚代码仓库:NEO的学习日记🚚
🌹关注我🫵带你学习排序知识
🔝🔝
缺省参数&函数重载
- 1. 前言
- 2. 缺省参数
- 2.1 全缺省
- 2.2 半缺省
- 3. 函数重载概念
- 4. 几种不同类型的函数重载
- 5. C++如何支持函数重载?
- 5.1 C程序为什么不支持函数重载?
- 5.2 C程序的链接过程
- 5.3 C++函数名修饰规则
- 6. 总结以及拓展
1. 前言
写C语言代码的时候
特别是在写数据结构时:
经常忘记传函数的参数
或者当前不需要什么参数
C++增加了缺省参数来解决这个问题
而为了解决相似功能的函数的函数名问题
C++增加了函数重载来解决这个问题
本篇文章将简单介绍缺省参数
并着重讲解函数重载的底层原理!
2. 缺省参数
缺省参数是声明或定义函数时
为函数的参数指定一个缺省值
在调用该函数时,若没有指定实参
则采用该形参的缺省值
否则使用指定的实参
缺省参数分类:
- 全缺省
- 半缺省
2.1 全缺省
类似于这样的代码:
void Func(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
全缺省指的是函数的所有参数都给缺省值
有四种调用此函数的方式:
- 什么都不传:
Func();
此时系统默认a,b,c的值分别为
10 - 20 - 30
- 只传一个参数:
Func(15);
此时,a的值为15
而系统默认b,c的值为:20-30
- 传两个参数:
Func(15,25);
此时a,b的值为:15 - 25
系统默认c的值为30
- 三个参数都传:
Func(15,25,35);
此时a,b,c的值为:15-25-35
注意: 传参不能写成这种形式:
Func(,25,);
Func(,,35);
Func(,25,35);
Func(15,,35);
2.2 半缺省
半缺省类似于这种形式:
void Func(int a, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
只要有参数没有给缺省值
那么它就是半缺省的
注意:
- 半缺省参数必须
从右往左
依次来给出,不能间隔着给 - 缺省参数不能在函数声明和定义中同时出现
- 缺省值必须是
常量
或者全局变量
比如下面这样定义半缺省是不行的:
void Func1(int a=10,int b,int c);
void Func2(int a,int b=20,int c);
//有缺省值的前提是它的右边的参数都有缺省值
3. 函数重载概念
以前有一个笑话:国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个
是男足。前者是“谁也赢不了!”,后者是“谁也赢不了
这里使用了一语双关.
而函数重载的概念和它类似:
函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
举个例子:
void func(int i,char ch) //函数1
{
//...
}
void func(char ch,int i) //函数2
{
//...
}
函数1和2可以同时存在
并且它们不是同一个函数
4. 几种不同类型的函数重载
总结三种支持函数重载的情况:
参数类型不同
int Add(int left, int right)
{
return left + right;
}
double Add(double left, double right)
{
return left + right;
}
参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
参数类型顺序不同
void f(int a, char b)
{
cout << "杭州电子科技大学" << endl;
}
void f(char b, int a)
{
cout << "圣光机联合学院" << endl;
}
(注意:下面这种不属于函数重载):
short Add(short x,short y)
{
return x+y;
}
int Add(short x,short y)
{
return x+y;
}
因为它们参数类型,数量,顺序都一样
只是返回值不同,不构成函数重载!
5. C++如何支持函数重载?
在C/C++中,一个程序要运行起来
需要经历以下几个阶段:
- 预处理
- 编译
- 汇编
- 链接
因为c++区别于c在这几个过程中
的差别,所以使C++能够支持函数重载
5.1 C程序为什么不支持函数重载?
定义两个源文件和一个头文件来解释:
- func.h
- func.c
- main.c
在.h文件声明两个函数
int func(int x,int y);
int func(int x,double y);
这三个文件会经历以下过程:
- 预处理阶段
主要内容:头文件展开,宏替换
条件编译,去掉注释
这个过程结束后,func.h被展开了
main.c和func.c源文件变成了:
func.i和main.i文件
- 编译阶段
主要内容:语法检查和生成汇编代码
这个过程结束后,func.i和main.i
文件变成了func.s和main.s文件
(此文件中为汇编代码)
- 汇编阶段
主要内容:将汇编代码转换成二进制码
以便机器能够读懂
这个过程结束后,func.s和main.s
文件变成了func.o和main.o文件
注:前面的过程只用了解,真正的主角在下面!
- 链接过程
func.o和main.o文件
以及链接过程是这部分的重中之重
5.2 C程序的链接过程
func.c到func.o和main.c到main.o
都是单线程的
链接过程:
.o的目标文件会合并到一起
其次还需找一些只给了声明的函数
的函数地址
而每一个.o文件都有一个符号表
符号表中存放函数的地址
当main文件要调用这个函数时
会去符号表中找函数的地址
而符号表中两个func函数的地址
编译器不知道应该调用哪个
所以c程序不支持函数重载!
5.3 C++函数名修饰规则
相比起C程序而言,C++新增了一个
函数名修饰规则来支持函数重载
这个规则就是将函数的参数带入符号表
所以参数的类型,数量,顺序不同
代表的是不同的函数,找地址时就不会出错!
我们在C++的汇编代码中找到了
这两个函数对应的部分:
综上所述:
函数参数的类型,数量,顺序不同
那么对应在符号表中的名字就不一样
main文件再去找函数地址时就不会冲突
对比c程序:
c程序符号表中只有一个函数名
函数参数没有参与进来
所以C程序不支持相同函数名的函数
6. 总结以及拓展
前面很多过程只是为了
后面的链接.o文件打基础
所以前面的听不懂也没关系
只需要知道C++有函数名修饰规则
c++的.o文件的符号表的函数名
和函数参数相关
而c程序的符号表和参数无关!
拓展:
C/C++函数调用约定和名字修饰规则
有兴趣好奇的同学可以看看里面
有对vs下函数名修饰规则讲解
C/C++约定