在实际的开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,但是这两个变量可能有多种类型:int、char、double、bool等。在C语言中,程序员往往需要分别设计出多个不同名的函数,但是在C++中,这完全没有必要。C++允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载。借助函数重载,一个函数名就可以有多种用途。
C++函数重载的条件:
- 1)函数名相同
- 2)函数参数个数不同(即:参数个数不同/参数类型不同/参数顺序不同)
函数重载的实现原理、
- C++代码在编译时会根据参数列表对函数名进行命重名(该技术被官方称为:name mangling),例如 void swap(int v1, int v2)会被重命名为 _swapii ,void swap(char v1,char v2)会被重命名为 _swapcc(不同的编译器会有不同的重命名规范,这里仅仅举例说明,实际情况可能并非如此)。当发生函数调用时,系统便会根据这些被重新命名的函数名去调用相应的函数。
- 因此从这个角度来讲,函数重载仅仅是语法层面上的,本质上它们还是不同的函数,占用不同的内存,入口地址也不一样。
例如下面的这些重载函数:
#include<iostream>
using namespace std;
void func(int,int)
{
}
void func(int)
{
}
void func(int,int,int)
{
void func(double,int)
{
}
void func(double,double)
{
}
int main()
{
func(200);
func(2,1);
func(100,200,300);
func(1.1,2.2);
func(10.1,2);
return 0;
}
我们编译后反汇编得到(g++,gdb):
0x00000000004006ed <+0>: push %rbp
0x00000000004006ee <+1>: mov %rsp,%rbp
0x00000000004006f1 <+4>: mov $0xc8,%edi
0x00000000004006f6 <+9>: callq 0x4006b3 <_Z4funci>
0x00000000004006fb <+14>: mov $0x1,%esi
0x0000000000400700 <+19>: mov $0x2,%edi
0x0000000000400705 <+24>: callq 0x4006a6 <_Z4funcii>
0x000000000040070a <+29>: mov $0x12c,%edx
0x000000000040070f <+34>: mov $0xc8,%esi
0x0000000000400714 <+39>: mov $0x64,%edi
0x0000000000400719 <+44>: callq 0x4006bd <_Z4funciii>
0x000000000040071e <+49>: movsd 0x11a(%rip),%xmm1 # 0x400840
0x0000000000400726 <+57>: movsd 0x11a(%rip),%xmm0 # 0x400848
0x000000000040072e <+65>: callq 0x4006dc <_Z4funcdd>
0x0000000000400733 <+70>: movsd 0x115(%rip),%xmm0 # 0x400850
0x000000000040073b <+78>: mov $0x2,%edi
0x0000000000400740 <+83>: callq 0x4006cd <_Z4funcdi>
0x0000000000400745 <+88>: mov $0x0,%eax
0x000000000040074a <+93>: pop %rbp
0x000000000040074b <+94>: retq
然后在查看符号表得到(readelf -s):
86: 00000000004006dc 17 FUNC GLOBAL DEFAULT 13 _Z4funcdd
89: 00000000004006cd 15 FUNC GLOBAL DEFAULT 13 _Z4funcdi
92: 00000000004006bd 16 FUNC GLOBAL DEFAULT 13 _Z4funciii
94: 00000000004006b3 10 FUNC GLOBAL DEFAULT 13 _Z4funci
111: 00000000004006a6 13 FUNC GLOBAL DEFAULT 13 _Z4funcii
发现了我们写的函数名称func被替换成了_Z4func开头的函数,这是因为在C++和C生成的符号表中,函数名的修饰规则是不同的,C++是函数名加参数类型,C就是函数名本身。也就是说C++中的同名函数重载,在底层来看其实是两个函数符号。
最后我们的核心:C++之所以有重载,其原因是函数名修饰规则不同
Comments NOTHING