函数重载

实现函数重载的条件

同一个作用域

参数个数不同

参数类型不同

参数顺序不同

//例子
//1. 函数重载条件
namespace A{
void MyFunc(){ cout << "无参数!" << endl; }
void MyFunc(int a){ cout << "a: " << a << endl; }
void MyFunc(string b){ cout << "b: " << b << endl; }
void MyFunc(int a, string b){ cout << "a: " << a << " b:" << b << endl;}
  void MyFunc(string b, int a){cout << "a: " << a << " b:" << b << endl;}
}
//2.返回值不作为函数重载依据
namespace B{
void MyFunc(string b, int a){}
//int MyFunc(string b, int a){} //无法重载仅按返回值区分的函数
}

注意点:

函数重载要防备二义性:

void MyFunc(string b){
cout << "b: " << b << endl;
}
//函数重载碰上默认参数
void MyFunc(string b, int a = 10){
cout << "a: " << a << " b:" << b << endl;
}
int main(){
MyFunc("hello"); //这时,两个函数都能匹配调用,产生二义性
return 0;
}

函数重载不能用返回值作为重载条件

函数重载实现原理

编译器为了实现函数重载,也是默认为我们做了一些幕后的工作,编译器用不同的参数类型来修饰不同的函数名,比如void func(); 编译器可能会将函数名修饰成func,当编译器碰到void func(int x),编译器可能将函数名修饰为func_int,当编译器碰到void func(int x,char c),编译器可能会将函数名修饰为_func_int_char我这里使用”可能”这个字眼是因为编译器如何修饰重载的函数名称并没有一个统一的标准,所以不同的编译器可能会产生不同的内部名。

 

void func(){}
void func(int x){}
void func(int x,char y){}
 

以上三个函数在linux下生成的编译之后的函数名为:

_Z4funcv //v 代表void,无参数
_Z4funci //i 代表参数为int类型
_Z4funcic //i 代表第一个参数为int类型,第二个参数为char类型

在C++中调用c语言的函数

方法1:添加extern "c"

extern "C"的主要作用就是用来在C++中调用c语言的代码

由于c++中需要支持函数重载,所以c和c++中对同一个函数经过编译后生成的函数名是不相同的,这就导致了一个问题,如果在c++中调用一个使用c语言编写模块中的某个函数,那么c++是根据c++的名称修饰方式来查找并链接这个函数,那么就会发生链接错误。例如,c++中调用MyFunc函数,在链接阶段会去找Z6Myfuncv,结果是没有找到的,因为这个MyFunc函数是c语言编写的,生成的符号是MyFunc。

那么如果我想在c++调用c的函数怎么办?

extern "C"的主要作用就是为了实现c++代码能够调用其他c语言代码。加上extern "C"后,这部分代码编译器按c语言的方式进行编译链接,而不是按c++的方式。

//例如
extern "c" void show();

方法2:来处理多个函数

在c语言对应的函数的头文件里面添加宏来处理:

#ifndef MYMODULE_H
#define MYMODULE_H

#include<stdio.h>


//从这里开始
#if __cplusplus
extern "C"{
#endif

void func1();
int func2(int a,int b);

#if __cplusplus
}
#endif //添加这一坨就好,在这里结尾

#endif

对于.c的实现头文件中的函数就正常实现就好了

同样在调用的cpp中这样用也是一样的