函数重载
一个词有多种含义,可以通过上下文来判断该词的真实含义,即该词被重载了。
“同一个函数名,由于参数个数不同、类型结构不同,在c++能够同时使用”
函数重载概念及分类
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数、类型、类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
注:函数重载时返回值的类型可以相同也可以不同。
参数类型不同
using namespace std;//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;
}int main()
{Add(25, 10);Add(2.5, 3.0);return 0;
}
参数个数不同
//2、参数个数不同
void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}int main()
{f();f(2.5);return 0;
}
参数类型顺序不同
//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()
{f(10, 'a');f('a', 10);return 0;
}
C++支持函数重载的原理
原因
在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参
数类型信息添加到修改后的名字中。
C++是通过函数修饰规则来区分的,只要参数不同,修饰出来的名字就不同,就支持了重载;
C语言是通过原本函数名称来查找的,因为同名函数没有办法区分。
原理分析
翻译的过程 | gcc命令 | 说明 | |
预处理 (进行宏替换) | gcc -E test.c -o test.i | -E 让gcc在预处理结束后,就停止编译 “从现在开始进行程序的翻译,预处理完成,就停下来” | 宏替换 去注释 头文件展开 条件编译 |
编译 (生成编译) | gcc -S test.i -o test.s | -S 只进行编译不进行汇编,生成汇编代码 “从现在开始进行程序的编译,汇编完成就停下来” | 检查代码规范性 检查语法错误 (确认无误后汇编) 将C语言代码翻译成汇编语言 |
汇编 | gcc -C test.o -o test.o | -C “从开始带现在进行程序的翻译”,汇编完成就停下来 | 将汇编语言编译成二进制目标文件 |
链接 | gcc test.o -o my.exe | 形成可执行程序 |
- 在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
- 在实际的项目中,是有很多个源文件构成的;
- 例如,如果A.cpp调用了B.cpp文件中的某个函数时,因为这个函数是在B.cpp文件中定义的,所以这个函数的地址就在B.o这个文件中;
- 那么链接就是解决这个问题的;
- 链接器看到A.cpp调用了这个函数,但是没有这个函数的地址,就会到B.o的符号表中找到这个函数的地址,然后链接在一起;
- 那么是如何找到B.o的文件,再通过B.o文件找到这个函数的地址呢?
- 每个编译器都有自己的函数名修饰规则;
- “由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字”;
- 通过下面我们可以看出:
- 在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
- 在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。
不同语言编译器函数修饰名字
通过gcc编译(C语言)的函数修饰后名字不变;
通过g++编译(C++语言)的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。