一.函数重载
在各种语言中,一个符号可以有多种含义,人们可以通过环境的整体来判断这个符号的含义,即该词被重载了.
例子:国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”
概念
函数重载:是函数的一种特殊情况,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;
}
注意
函数返回值为什么不可以作为函数重载条件?
原因就是:编译器在编译时,不会去判断函数的返回类型!也就是说你返回类型虽然不同,但是只有函数调用以后,编译器才去验证返回类型。
总结
函数重载满足条件:
- 同一个作用域下
- 函数名称相同
- 函数参数类型不同或者个数不同或者参数的顺序不同
C++函数重载的原理
C++支持函数重载,而C语言不支持函数重载,这是为什么呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接
- 实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o(a.cpp可重定位目标文件.o)中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o(b.cpp可重定位目标文件.o)中。那么怎么办呢?
- 这个时候需要链接来处理,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起
- 那么链接时,面对Add函数,链接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则.
- Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字
- 下面可以看出gcc的函数修饰后名字不变,而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】
- C++:
- C:
在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。 - Windows下名字修饰规则:
对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了