前言
本文将讲述,函数重载及简述其实现原理。
🕺作者: 迷茫的启明星
😘欢迎关注:👍点赞🙌收藏✍️留言
🏇家人们,码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢阅读!!!
持续更新中~
函数重载
在汉语中,一个词可以有多重含义,在之前朋友圈经常刷到的一句话:
“以前我喜欢一个人,现在我喜欢一个人”
怎么理解呢?
可以是以前喜欢一个人自由自在的,现在喜欢上了另一个人
也可以是以前喜欢过一个人,但是被情所伤,现在喜欢自己一个人生活
在C++中也有相同的应用:函数重载
函数重载的概念
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
1、 参数类型不同
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; }
2、参数个数不同
void f() { cout << "f()" << endl; } void f(int a) { cout << "f(int a)" << endl; }
3、参数顺序不同
void f(int a, char b) { cout << "f(int a,char b)" << endl; } void f(char b, int a) { cout << "f(char b, int a)" << endl; }
那么返回值不同,能构成重载吗?不能,因为调用的时候不能区分
int f(double d) { } void f(double d) { }
缺省值不同呢?不能,因为调用的时候不能区分
void f(int a) { cout << "f()" << endl; } void f(int a = 0) { cout << "f(int a)" << endl; }
一个无参、一个有参但是是全缺省:构成重载但是使用时会出问题,调用存在歧义
void f() { cout << "f()" << endl; } void f(int a = 0) { cout << "f(int a)" << endl; } int main() { f(); // 调用存在歧义 return 0; }
函数重载原理
我们都知道C语言是不能重载的,但是为什么不能呢?
我们先来验证一下C语言是否真的不能重载
显然 是不能的
那么是为什么呢?
这与C语言编译器有关
这就不得不提程序是怎么运行起来的
show.c show.h test.c
预处理–>头文件展开、宏替换、条件编译、去掉注释
show.i test.i
编译–>检查语法,生成汇编代码
show.s test.s
汇编–>汇编代码转换为二进制代码
show.o test.o
链接–>合并段表
a.out
再简单介绍一下链接的工作:
如果当前文件有函数的定义,那么再编译时就填上地址了
如果当前文件只有函数的声明,那么定义就在其他的源文件中,
编译时没有地址,只能再编译的时候去其它.o符号表中1根据函数修饰名字去找
在C语言中不能实现重载的原因是,汇编和链接时对函数的修饰名规则所致,
它在调用时仅仅使用函数名来区分,如果在show.c文件中去写一个重载的函数,
汇编时在show.o 符号表中存在歧义和冲突,在链接的时候也存在歧义和冲突,
因为它们都是直接使用函数名去标识和查找的,而函数名相同。
而在C++中,它的目标文件符号表不是直接使用函数名来标识和查找函数的,
它有与C不同的函数名修饰规则,但是这个规则不同的编译器下面不同,
有了函数名修饰规则,只要参数不同,
show.o 符号表里面重载的函数就不存在歧义和冲突了,
在链接的时候,test.o的main函数里面去调用两个重载的函数,查找地址时也是明确的。
linux下的g++的修饰函数名规则(也就是对C++的)
_Z + 函数名长度 + 函数名 + 参数首字母
示例:
void f(){} void f(int a){} void func(int a,int*p){}
linux下的C语言的修饰函数名规则
void f(){} void func(int a,int*p){}
以上可以验证前面所说的函数名修饰规则。
总结
本文讲述了,函数重载及简述其实现原理,下一篇将讲述引用&
respect !
下篇见!