c++函数重载及其实现原理

在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 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;
}  

报错-有歧义问题—编译器不知道调用以上哪一个函数

扫描二维码关注公众号,回复: 1840555 查看本文章
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)"<<endl;
}
void Funtest(int a)
{
    cout<<"void Funtest(int)"<<endl;
}

结论:不可以构成函数重载,不满足重载构成三条件。

猜你喜欢

转载自blog.csdn.net/tanrui519521/article/details/79924423