在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 int、float、char、bool 等,我们需要通过参数把变量的地址传入函数内部。在C语言中,程序员往往需要分别设计出三个不同名的函数,其函数原型与下面类似:
void swap1(int *a, int *b); //交换 int 变量的值
void swap2(float *a, float *b); //交换 float 变量的值
void swap3(char *a, char *b); //交换 char 变量的值
void swap4(bool *a, bool *b); //交换 bool 变量的值
但在C++中,这完全没有必要。C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading)
函数重载是函数的一种特殊情况,c++允许在同一作用域中声明几个功能类似的函数,这些函数的形参列表必须不同,常用来实现功能类似类型不同的问题。
int Add(int left,int right)
{
Return left+right;
}
Double Add(int left,int right)
{
Return left+right;
}
Char Add(int left,int right)
{
Return left+right;
}
/*********************************************/
int main()
{
Add(1,2);//整型
Add(1.0,2.0);//浮点型--默认是double类型 若变成float型 -->Add(1.0f,2.0f);
Add(‘1’,‘2’);//字符型
}
结果:-->编译时会进行参数类型推演,检测参数类型选择相匹配的函数类型
3
3.0
C //说明:(字符1的ASC码是49;字符2的ASC码是50--->打印ASCC码为99的字符)
函数重载条件:
1:必须在同一个作用域。
2:函数名字必须相同
3:形参列表必须不同
①参数个数不一样
②参数类型不一样
③参数类型次序不同
例:
void Funtest(){}
void Funtest(int a){} //①
void Funtest(int a){}
void Funtest(char a){}//②
void Funtest(int a,char a){}
void Funtest(char a,int a){}//③
此外:
①仅仅返回值不同是不能构成函数重载的—原因:调用不明显
例:
void Funtest(){}
Int Funtest()
{
Return 0;
}
②报错-有歧义问题—编译器不知道调用以上哪一个函数
void Funtest(){}
void Funtest(int a=10){}
Int main()
{
Funtest();
Return 0;
}
那么为什么c++支持函数重载而C语言不支持函数重载呢?这就与C和C++中,编译器对函数名字的修改规则相关。
C与C++中,编译器对函数名字的修改规则:(c++函数重载底层处理)
我们以vs编译器下为例作出验证:
在c++底层有重命名机制。
例:
int Add(int left,int right);
编译之后函数名修改为(?Add@@YAHHH@Z)
Char Add(int left,int right);
编译之后函数名修改为(?Add@@YADHH@Z)
那么我们从上面可以知道,在c++中,底层的重命名机制将Add函数根据参数的个数,参数的类型,返回值的类型都做了重新命名。给定了返回值类型和参数类型,所以在编译之后,不会有重定义情况出现。
而C语言中,编译之后C语言链接器将函数名改为_Add ,没有给定返回值类型和参数类型,所以会重定义。
那么,c++能否将一个函数按照c的风格来编译呢?
答案肯定是可以的。
我们在C++ 程序中调用被 C 编译器编译后的函数时,添加extern “C”
Extern “C” int Add (int left ,int right)
原因:
①C++语言支持函数重载。而C不支持函数重载。
②函数在C中和C++中编译过的函数名字是不一样的。加上extern”C”是说明是说明C已经编译过的。
C++想要调用已经编译过的C函数,由于编译过的名字不同,是不能直接调用的,所以C++加extern“C”生命来解决这个问题。
例如:假设某个函数的原型为: void foo(int x, int y);该函数被C 编译器编译后在库中的名字为_foo, 而C++ 编译器则会产生像_foo_int_int 之类的名字,加上extren”C”后,就相当于告诉编译器,函数foo是个C编译后的函数,在库里应该找的是_foo,而不是_foo_int_int.
思考:
仅是否带缺省参数区别的函数,会构成重载吗?
例如:
void Funtest(int a = 10)
{
cout<<"void Funtest(int)"<void Funtest(int a)
{
cout<<"void Funtest(int)"<