C++函数重载实现原理浅析
----------------------------------------献给所有和我一样还没拿到office的同学-----------------------------------------------------------------------------------
C++函数重载实现原理浅析
C++实现函数重载的技术手段是函数符号改名,所以我们可以通过分析编译器的函数符号改名机制来验证C++函数重载规则。
1.函数重载的概念
函数重载出现在相同作用域中的多个函数,具有相同的名字而形参表不同。
注意:不能仅仅基于不同的返回类型而实现函数重载。返回值是不影响函数签名的。
2.函数调用:
函数调用时会发生什么?学过8086汇编时,我们都知道函数调用是程序执行点跳转到一个符号所在的地方转而执行符号所在地址的代码,然后再跳回去。这个符号就是函数。
我们用一个简单的例子来说明一下函数调用
//在这个简单的实例中,我们只是简单的在main函数中调用了一下printhello函数来打印hello world!
[cpp
#include <stdio.h>
void printhello()
{
printf("hello world!\n");
}
int main()
{
printhello();//这里调用函数printhello
return 0;
}
[cpp] view plaincopyprint?
//函数调用部分对应的汇编代码为:
main:.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, %eax
call printhello ;这里call printhello,跳转到符号printhello出执行
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
C语言中函数符号名和对应的函数名是一样的,而C++为了支持函数重载,符号名是在对应的函数名上改编的。如下图所示,函数名为func,而对应的符号名为_Z4funcv。
3.C++的函数符号命名规则
在前面的的图示中,我们给出了C++函数编译符号实例,貌似函数名是对应符号的子串额。实际上函数的编译符号是根据函数名,函数的参数表(包括参数类型和数量)相关的。而且不同的编译器的命名规则不一样。只要能保证相同的函数名和不同的函数参数列表生成的符号名不一样就行。下面我们来感受一下GCC的C++编译器的命名规则。
3.1函数返回类型不影响生成的符号名
前面我们说不能仅仅基于不同的返回类型而实现函数重载,原因是函数返回值并不影响最后生成的符号。我现在就验证一下:
我们分别在两个cpp文件中定义两个同名但返回值不同的函数,看一看他们在汇编代码中的符号是否一样。
第一个函数返回类型为void,生成的符号名为:_Z4funcv
第二个函数名也为func,但返回类型为int,生成的符号名还是为:_Z4funcv
上面两个同名但返回值类型不同函数生成相同符号名,说明返回类型是不影响符号名的。如果你定义两个函数,只是返回类型不同,那么它们生成的符号一样,肯定会发生符号重定义错误。
补充:软件开发 , C++ ,