四、函数重载
c语言不允许定义同名函数,但是c++能够通过函数重载定义同名函数
C++中重载函数通常用来命名一组功能相似而数据类型不同的函数:函数重载是指在同一作用域内,一组函数名相同,不同参数列表(不同参数个数 或 不同类型 或 不同顺序)的函数,这组函数被称为重载函数。
函数重载作用:减少了函数名的数量,避免了名字空间的污染,增加了程序可读性。
如下3个Add函数构成重载,它们的参数类型都不相同,参数类型分别是int、double、long
1. #include<iostream> 2. 3. int Add(int left, int right) 4. { 5. return left + right; 6. } 7. 8. double Add(double left, double right) 9. { 10. return left + right; 11. } 12. 13. long Add(long left, long right) 14. { 15. return left + right; 16. } 17. 18. int main() 19. { 20. Add(10, 20); 21. Add(10.3, 20.5); 22. Add(10L, 20L); 23. 24. return 0; 25. }
注意1:函数是否重载取决于同名函数参数列表是否相同,函数重载和函数返回值类型没有关系。
如下两个函数不是函数重载,编译会报错,因为参数列表相同,不构成重载,尽管返回值类型不同,但函数重载定义并不关注返回值类型。
1. int Add(short left, short right) 2. { 3. return left + right; 4. } 5. 6. short Add(short left, short right) 7. { 8. return left + right; 9. }
注意2:带缺省参数的函数和原函数不算重载
如下两个函数参数类型、个数、顺序都相同,不构成重载
1. int Add(int left, int right) 2. { 3. return left + right; 4. } 5. 6. int Add(int left = 2, int right = 3) 7. { 8. return left + right; 9. }
另外,虽然下面的两个f函数构成重载,但是调用时报错,因为16行对f函数进行调用时,编译器并不知道是该匹配两个参数的f函数还是该匹配带有缺省参数c的f函数,因此会报错。
1. void f(int a, int b, int c=1) 2. { 3. 4. } 5. 6. void f(int a, int b) 7. { 8. 9. } 10. 11. int main() 12. { 13. f(1, 2); 14. f(1, 2, 3); 15. 16. return 0; 17. }
c/c++编译过程:
在linux环境中,创建f.h文件,写如下代码:
创建f.cpp文件,写如下代码:
创建main.c文件,写如下代码:
执行g++ -o cpp f.cpp main.cpp
编译通过,生成cpp可执行文件
执行objdump -S cpp
生成汇编代码:
main.cpp的#include "f.h"包含了f.h文件,f.h文件只是包含了两个add函数的声明,在编译阶段,编译器会认为函数定义在其他地方,而让函数编译通过,等到链接时,再找函数的定义。
链接时,通过函数名即函数地址去其他目标文件中找add的地址,如果找到了就填上add的地址。
根据c++函数名修饰规则,只要参数不同,修饰出来的函数名就不同,这就支持了重载:把参数类型首字母带进函数名中,参数不同,函数签名就不同。
_Z3addii函数名中,_Z是前缀,3是函数的字符长度(add长度为3),ii是两个参数类型int的首字母
同理,_Z3adddd函数名中,_Z是前缀,3是函数的字符长度(add长度为3),dd是两个参数类型double的首字母。
以上也能看出c++函数签名和返回值类型无关。
那么,对于c语言直接拿函数名做名称,无法支持定义两个同名函数
f.h
f.c
main.c
执行 执行g++ -o test f.cpp main.cpp
编译通过,生成test可执行文件
执行objdump -S test
生成汇编代码:
C语言无法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,这就支持了重载。