本文首发于个人博客
函数重载(Overload)
C语言中没有函数重载
C++语言中有函数重载
函数名相同,参数个数不同、参数类型不同、参数顺序不同
例如下面就是函数重载
1 | void sum(int a, int b){ |
返回值类型与函数重载无关
返回值类型与函数重载无关,下面代码不构成重载,编译会报错
1 | //返回值类型与函数重载无关 |
实参的隐式类型转换可能会产生二义性
不同编译器有不同处理
下面代码在vs上编译不过,但是在Xcode中可以编译通过。
1 |
|
函数重载的本质
- 采用了name mangling或者叫name decoration技术
- C++编译器默认会对符号名(比如函数名)进行改编、修饰,有些地方翻译为“命名倾轧”
- 重载时会生成多个不同的函数名,不同编译器(MSVC、g++)有不同的生成规则
- 通过IDA打开【VS_Release_禁止优化】可以看到 或者通过hopper查看
源码
下面的代码
1 |
|
在代码中,void sum(double a){}
和 void sum(int a){}
是如何重载,调用函数的时候是如何能正确找到对应的函数呢?
汇编
我是用xcode的编译出可执行文件,放在hopper中查看
1 | __Z3sumd: // sum(double) |
可知 void sum(double a){}
被编译器修改为函数__Z3sumd
1 | __Z3sumi: // sum(int) |
可知 void sum(int a){}
被编译器修改为函数__Z3sumi
这样当我们调用的时候
1 | int main(){ |
汇编如下,可知:因为 10.5是double类型,调用函数的时候是调用 __Z3sumd
1 | 0000000100000de0 push rbp |
函数重载结论
由上面的汇编代码可知,当参数类型不同的时候,编译器会生成不同的函数名作为区别,这样就能实现函数重载。
默认参数
规则
C++允许函数设置默认参数,在调用时可以根据情况省略实参。规则如下:
- 默认参数只能按照右到左的顺序
- 如果函数同时有声明、实现,默认参数只能放在函数声明中
- 默认参数的值可以是常量、全局符号(全局变量、函数名)
用法:如果函数的实参经常是同一个值,可以考虑使用默认参数
1 |
|
可能有冲突,二义性
- 函数重载、默认参数可能会产生冲突、二义性(建议优先选择使用默认参数)
例如下面的代码中, 调用test(3);
会报错,因为不知道要执行哪个函数。
1 |
|
总结:如果函数的实参经常是同一个值,可以考虑使用默认参数