什么是函数重载?
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题
int add(int a, int b)
{
return a + b;
}
double add(double a,double b)
{
return a + b;
}
因此,以上两个函数即为典型的函数重载。
int add(int a, int b)
{
return a+b;
}
double add(int a, int b)
{
return(double)a + b;
}
而仅仅只有返回值不同的两个函数,并不是函数重载。
那么,为什么C++支持函数重载,而C语言不支持函数重载呢?
通过之前对C语言程序环境和预处理的学习,我们知道,在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
假设以项目中包含test.c , main.c , test.h 为例
- 预处理
:头文件展开(test.h)、宏替换、条件编译、去掉注释
test.c —> test.i
main.c —> main.i
- 编译:检查语法,生成汇编代码
test.i —> test.s
main.i —> main.s
- 汇编:把汇编代码转成二进制机器码
test.s —> test.o
main.s —> main.o
- 链接:在main.c中,通过所调用函数的函数名,去test.c的符号表中找到对应的地址,合在一起。
在这个过程中,如果找不到,就会报错,也就是我们常说的链接错误。如下图。
下面我们使用Linux来模拟C语言的链接过程。
首先,创建一个test.c文件并写入。
接着对test.c进行编译,发现编译通过。同时生成了a.out文件
接着,我们继续写入test.c
出现了错误
我们使用一个指令来查看目标文件中的符号表,发现此处直接取的是函数名。
如果有多个同名函数,在链接时,无法通过函数名去找地址。这也就很好的说明了为什么C语言不支持函数重载。
我们再来看一下C++的情况:
C++的函数名按照规则在符号表中被修饰。因此,在C++中,重载函数只要形参列表(参数个数 或 类型 或 顺序) 不同,修饰后的函数名就不同。那么在链接时,就不会因名字冲突而找不到对应地址。
同时,这也很好的解释了“ 为什么函数重载仅仅只有返回值不同是不可以的 ”这一问题。