函数重载
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数。
这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
1、参数类型不同
#include<iostream>
using namespace std;
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 main()
{
Add(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}
函数重载底层原理
short Add(short left, short right)
{
}
int Add(short left, short right)
{
}
这种情况属于函数重载吗?
答:这种是不构成函数重载的,这是因为函数重载跟返回值没有关系,在VS2019下编译器也会主动报错。
那么今天我们就是来底层深挖,为什么和返回值没有关系,又为什么和参数的顺序,个数,类型有关系呢?
为什么C++支持函数重载,而C语言不支持函数重载呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
在编译的过程中还会生成一个符号表,主要记录函数定义和函数地址的映射,那符号表为什么要生成函数地址的映射呢?
在main函数的指令中,有两句指令call,call后面所跟的就是函数的地址,函数的名字和函数的地址。然后我们来看一下这个过程,真正的函数地址就是第一句指令的地址。函数的名字也会有自己的命名规则。
为了更好的看函数的命名规则,我们在linux下看看这个细节。当函数名相同,参数不同时,他们的函数名会有一套新的命名规则。在不同的话函数调用中,他们参数类型首字符带进命名规则中去了。
新的函数名:_Z 函数名长度 函数名 类型首字母
我们再在Linux下看看C语言是如何处理函数名的:
此时我们发现C语言对函数的命名只有函数名本身,和参数无关。
因此我们知道C语言对函数的命名只有函数名本身,因此如果在C语言中,函数名相同时,就会报错,因此C语言是不支持函数重载的。
总结:
1.C++支持函数重载是因为C++在符号表中存储的函数的定义和函数的地址。C++中对函数的命名规则有了新的变化:_Z 函数名长度 函数名 类型首字母 。
因此参数的类型个数,顺序不同就会不同的命名。名字不同地址不同。这也是为什么C++支持函数重载的原因。
2.我们发现在新的命名规则中是不包括返回值类型的,因此返回值类型不同并不会对函数的命名产生影响,这也是返回值不构成函数重载的原因。
3.C语言中在生成符号表中存储的只是原函数的名字,那么如果函数的名字相同时就会产生命名冲突。这就是为什么C语言不支持函数重载的原因。