C语言中我们知道创建的函数是不能同名的,但是在C++中却是可以的,这就是C++中的函数重载(函数名相同,参数列表不同),而函数重载有三种:函数参数类型不同、参数的数量不同、参数的顺序不同。所以就先浅浅的了解一下函数重载:
函数重载
参数类型不同
int Add(int a, int b)
{
return a + b;
}
double Add(double a, double b)
{
return a + b;
}
int main()
{
int a1 = Add(3, 4);
double a2 = Add(3.4, 4.3);
cout << "a1 = " << a1 << endl;
cout << "a2 = " << a2 << endl;
return 0;
}
参数个数不同
int Add(int a, int b)
{
return a + b;
}
double Add(double a, double b,double c)
{
return a + b + c;
}
int main()
{
int a1 = Add(3, 4);
double a2 = Add(3.4, 4.3, 2.6);
cout << "a1 = " << a1 << endl;
cout << "a2 = " << a2 << endl;
return 0;
}
参数顺序不同
double Add(int a, double b)
{
return a + b;
}
double Add(double a, int b)
{
return a + b;
}
int main()
{
double a1 = Add(3, 4.3);
double a2 = Add(3.2, 4);
cout << "a1 = " << a1 << endl;
cout << "a2 = " << a2 << endl;
return 0;
}
double Add(int a, double b)
{
return a + b;
}
double Add(double a, int b,double c)
{
return a + b + c;
}
int main()
{
double a1 = Add(3, 4.3);
double a2 = Add(3.2, 4, 2.6);
cout << "a1 = " << a1 << endl;
cout << "a2 = " << a2 << endl;
return 0;
}
其实像这种同时满足了上面的条件也是属于函数重载的,所以要发挥你的想象。
同时有一点极为重要:返回值类型不能作为重载依据。主要是针对返回值不同,参数列表一致的函数。因为在调用函数时,如果仅考虑函数调用表达式本身,编译器无法确定应该调用哪一个函数,因为可以忽略返回值(如
func(1)
这样的调用)注:函数重载需在同意作用域内,可以不在同一个源文件下。
为什么C语言不支持函数重载C++可以
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。C语言程序环境_c语言环境_小猴zhi永不言弃的博客-优快云博客可借鉴
C语言中会在编译阶段进行符号表汇总,就是记录在进入主函数之前所创建的全局变量和函数名这些数据。
在汇编阶段就会将这些数据存在符号表当中,并且每个数据都对应着各自的地址(对于函数而言:地址是在函数定义时才会出现,即形成汇编代码时的第一句指令所在的地址就是该函数符号的地址)
寻址的步骤是在链接阶段。链接时,编译器将所有源文件的符号表进行合并最终还在链接阶段将这些符号表合并与重定位,也就是将那些具有相同符号名的数据地址进行合并成一个有效的地址符号名。
所以话说回来,在C语言当中如果遇到同名函数(函数重载)时,在在编译阶段的语法分析阶段时就会出错,将两个同名的函数放到符号表,生成相对应的地址,而且地址还不相同,最后进行符号表汇总时就会出现问题。
编译后函数名变化只是在原来的函数名前加了一个下划线,所以当同名的函数参数不同时,编译器无法解析到他们的不同,因为它们编译后的名称都相同,所以C语言不能函数重载
C++其实和C语言经历的阶段是相同的,但是C++在这里做了优化的,在编译阶段时也是进行相同的符号表汇总,但是函数重载在C++中并不是看作相同符号名的函数,而是视作不同符号名的函数,所以这里C++是引入了函数名修饰规则。
而函数名修饰就是将你所生成符号表时的函数名进行一定的修改,而C语言对于函数名修饰就是加一个下滑杠_,而C++就比较复杂,不同编译器的函数名修饰出来的效果也都不相同。
VS中MSVC 编译器对同一个函数名(func)的修饰:(HN交换了位置)
而gcc编译器对函数名的修饰是:_Z + 函数名长度 + 函数名 + 参数类型的缩写。比如,
int Add(int a, double b)就变成了_Z3Addid
所以回到问题,C语言不支持函数重载的原因:
- C 语言编译器在编译时,是通过函数名来识别函数的,不会去考虑参数类型、参数个数这些特征,只要函数名相同就认为是重复定义,而函数重载需要依靠不同的参数列表(参数个数、参数类型等不同)来区分同名函数,这一点 C 语言机制不支持。
- C 语言没有像 C++ 那样的函数名修饰机制,C++ 中编译器会根据函数的参数等情况对函数名进行修饰,使得同名但参数不同的函数最终有不同的内部标识,而 C 语言不存在这样的处理,所以无法实现函数重载。