函数重载的底层原理C++
先写一条感想:语言的强大源自编译器的强大;
函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串,用来指明函数的定义或原型。LINK程序或其他工具有时需要指定函数的名字修饰来定位函数的正确位置。由于c语言不支持函数重载,而c++语言支持函数重载,所以c和c++的函数名称修饰规则是不相同的。
C语言将上面的函数名称处理为_Add,即其修饰规则为_函数名(函数名前加_)。
因此,
对于C语言,相同的函数名,其修饰名必然相同,与参数无关,因此不同参数的同名函数的修饰名是重复的,因此无法同时存在,更无法实现重载;
C++之所以能够实现重载,是因为编译器能够区分同名不同参的函数,而其区分的底层原理就是对原函数名进行修饰,或者叫重命名;
编译前的重载函数(同名不同参的函数),编译后就是不同名的函数,这个新的函数名中不仅包含了原名,还包含了参数信息;
编译前的函数名:尔康,尔康,尔康,尔康
编译后的函数名:愤怒的尔康,哭泣的尔康,卖萌的尔康,睡觉的尔康
函数重载:尔康(愤怒),尔康(哭泣),尔康(卖萌),尔康(睡觉)
c++语言的函数名称修饰规则:
[window系统下vs2010]:
c++语言将上面的函数名称处理为?Add@@YAHHH@Z
(1)其中‘?’标识函数名的开始,其后跟函数名;
(2)“@@YA”标识参数表的开始,其后跟的第一个字符代表函数的返回值类型,接下来的字符依次代表函数参数列表中各个参数的类型;
类型的代号:
x--void ,
d--char,
e--unsigned char,
f--short,
h--int,
i--unsigned int,
j--long,
k--unsigned long,
m--float,
n--double,
_n--bool,
... ...
所以@@yg后面的HHH分别代表三个int类型,其中第一个为函数返回值,后面两个为参数类型。
(3)@z标识整个名字结束。
[Centos]:
c++语言将上面的函数名称处理为_Z3Addii。
其中_Z代表开始,3代表函数名的字符个数,其后跟函数名(这里为Add),再加上参数类型(这里ii代表有两个整型的参数)。
通过上面的分析,我们发现不同的编译器对函数名称修饰的规则是不同的,但我们依然可以找到规律,c语言对函数名称修饰的处理只关注到了函数名;而c++语言除了函数名,还关注了函数的参数,通过对函数名称的修饰不同,编译器调用函数时所找的符号就不同,因而c++语言支持函数重载。也可得出构成函数重载的条件为函数名相同,参数不同,返回值类型可同可不同。