C++解剖之函数重载
什么叫函数重载?
函数重载是C++允许在同一个作用域声明几个功能类似的同名函数;要求是:同名的函数的形参列表(参数个数、参数类型或顺序)不同。
int add(int x,int y);
double add(double x,double y);
//这里的函数名add是相同的,但里面的参数类型不同,故这两个函数是重载的
注意:函数重载是C++特有的功能;C语言不支持函数重载。
但这时候我们肯定会有一点点疑问:Why……
为什么C++支持函数重载,而C语言却不支持?
在解释这个问题之前,首先我们理一下程序在编译和链接的过程:
- 预处理阶段(头文件展开、宏替换、消去注释部分、条件编译);
- 编译阶段(检查语法,生成汇编代码);
- 汇编阶段(将汇编码转换成二进制机器码);
- 链接(将各个模块链接到一块生成可执行程序)。
这里只是解决问题的开端,到这里,我们必须明白的是:
- 在编译阶段,就会去访问函数的地址,但这个时候其实是找不到的,不过,函数的声明会帮我们解决掉这个麻烦,后面只需要在链接时找到函数地址就可以了;
- 每个目标文件会在汇编阶段生成对应的符号表,链接时就能利用这个符号表找到目标文件中的函数地址了。
其实,在这个时候,我们好像还没进入主题:为什么C++支持重载?
不要着急,这时候,我们还会引进一个新概念来帮助我们解决该问题——函数名修饰规则。
函数名修饰规则
在C++中,函数名的修饰规则会出现在链接阶段——找函数地址阶段;
- 函数名修饰规则是支持重载的,但是函数重载时,由于函数名相同,好像是无法找到重载函数各自对应的地址。
下面将介绍在Linux系统下函数重载对应的地址的表示:
int add(int x,int y);//Z3addii
double add(double x,double y);//Z3adddd
//其中Z3addii和Z3adddd是链接时的找到该函数的名称
//Z3表示一个前缀
//add表示函数名
//ii表示参数类型int的首字母;dd表示参数类型为double的首字母
- 看了上面例子之后,我想大家应该已经能大致理解为什么C++能够支持重载了;
- 不过,大家还是跟我理一遍思路好了:在C++中,由于函数名的修饰规则,在找函数地址时所找的的符号表是由函数名和参数类型的首字母组成的,这时,即使重载的函数名相同,但只要参数的类型、个数或者顺序不同,它们对应的地址就是不同的;但是在C语言中,找到的函数地址对应的符号表就直接是由函数名构成的,这样自然是不能支持函数重载的。
最后,不知道我讲的是否足够清晰,如有不足,那就欢迎大家批评指正啦!