C++之函数重载

简单介绍了一下函数重载,大致讲解了一下Linux与 VisualStudio中函数名修饰规则。

目录

什么是函数重载 

为什么要函数重载

为什么可以函数重载


什么是函数重载 

函数重载

C++允许在同一作用域中声明几个功能类似的同名函数,但是这些同名函数的参数个数或参数类型或不同类型参数顺序必须不同,即参数列表不同,也就是说用同一个函数完成不同的功能。

int add(int a , int b , int c) {
    cout << "int add(int, int, int)" << endl;
    return a + b + c;
}

int add(int a, int b) {
    cout << "int add(int, int)" << endl;
    return a + b;
}

int add(float a, int b) {
    cout << "int add(float, int)" << endl;;
    return a + b;
}

int add(int a, float b) {
    cout << "int add(int, float)" << endl;
    return a + b;
}


int main() {
    cout << endl;
    cout << add(1, 2) << endl;
    cout << add(1.2f, 2) << endl;
    cout << add(1, 4.3f) << endl;
    cout << add(1, 2, 3) << endl;
    return 0;
}

 

可以看出,编译器会根据输入参数的个数输入参数的类型输入的不同类型的参数的顺序自动匹配到相应的函数进行处理。在实际应用中,如果编译器可以通过隐式类型转换找到匹配的结果,就会直接调用,否则就会报错。

但是,如果函数之间仅仅是返回值类型不同,是无法进行重载的,因为只是返回值类型的差异,编译器无法根据函数名及传入参数识别出我们所要调用的是哪一个函数。

注意:一般情况下,函数重载时不要设置缺省参数,容易导致编译器不知道我们所要调用哪一个函数,产生报错。

为什么要函数重载

我们在编写代码的时候经常会使用到一系列功能相似的函数,如果为每个函数都命一个名,很容易出现重复,造成名字空间的污染。

为什么可以函数重载

名字修饰:

我们都知道C/C++代码需要经过:预处理,编译,汇编,链接四个阶段才可以运行起来。 

编译器在编译过程中,会对代码中使用的函数名按照编译器自己的规则来进行修饰。C语言中的修饰规则非常简单,只是在函数名前边加上一个下划线,并没有其它过多地修饰,所以在C语言中同名函数经过修饰后依旧是同名函数,所以C语言中无法进行函数重载。 

同理,C++之所以可以支持函数重载,是因为其函数名地修饰规则与C语言不同。我们在Linux下使用gcc -c对上方代码进行编译,通过nm -s对文件内符号及其对应映射进行查询显示,可以得到如下结果。

可以看到,我们的代码经过编译后得到的修饰后符号列表中,有着4个与add相关的函数名符号:

_Z3addfi -> int add(float,int)
_Z3addif -> int add(int,float)
_Z3addii -> int add(int,int)
_Z3addiii -> int add(int,int,int)
int add(int a , int b , int c) {
    cout << "int add(int, int, int)" << endl;
    return a + b + c;
}

int add(int a, int b) {
    cout << "int add(int, int)" << endl;
    return a + b;
}

int add(float a, int b) {
    cout << "int add(float, int)" << endl;;
    return a + b;
}

int add(int a, float b) {
    cout << "int add(int, float)" << endl;
    return a + b;
}

这刚好与我们代码中add的4个重载函数相对应,并且再通过编写其它重载函数大致可以得出其函数名修饰规则为:

_Z + 函数名长度 + 函数名 + 参数1类型首字母 + 参数2类型首字母 + ...

 而在VisualStudio中编译时,通过“不择手段”,我们可以得到其修饰后的函数名为:

 乍一看,这是个什么玩意?

?add@@YAHHHH@Z -> int add(int,int,int)
?add@@YAHHH@Z -> int add(int,int)
?add@@YAHMH@Z -> int add(float,int)
?add@@YAHHM@Z -> int add(int,float)

仔细一看,这是个什么玩意?

通过查阅资料及采用更多示例,可以大概得出其命名规则为:

? + 函数名 + 函数调用约定 + 返回值类型符号 + 参数1类型符号 + 参数2类型符号 +... + @Z
函数调用约定修饰符号
__stdcall@@YG
__cdecl@@YA
__fastcall@@YI
参数类型符号
Xvoid
Dchar
Eunsigned char
Fshort
Hint
Iunsigned int
Jlong
Kunsigned long
Mfloat
Ndouble
_Nbool
......

 正是因为C++对于函数名的修饰中加入了对函数参数的修饰,所以C++中可以分辨出参数列表不同的“同名函数”。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云雷屯176

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值