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