C++ - 了解Name Mangling


名字粉碎?命名粉碎?名称改编?
or 命名倾轧(实属拗口)?
在这里插片描述

函数重载

函数重载

为方便使用,C++允许在同一范围内声明几个功能类似的同名函数,但是这些同名函数的形式参数(个数、类型、顺序)必须不同,也就是说用同一个函数完成不同的功能。
:在C语言中,不支持函数的重载,即C语言中一个函数不能与另一个函数重名。

重载原则

①函数名相同,函数的参数列表不同(个数、类型、顺序);
②匹配原则1:严格匹配,找到再调用;
③匹配原则2:通过隐式类型转换寻求一个匹配,找到则调用;
④返回值类型不构成重载条件。

什么是 Name Mangling?

Name Mangling 是C++ 函数重载的底层实现原理
被翻译成为:“名字粉碎”、“命名倾轧”;(用这个的人比较多,可能因为看起来比较晦涩、难懂,从而显得高大上?(瞎猜的));
以此来改名函数名,区分参数不同的同名函数。

Name Mangling 如何实现的?

通过查看符号表来举例:

  • 我们先准备一个很简单的cpp文件(test.cpp):
    在这里插入图片描述
  • 接着g++编译它:
    在这里插入图片描述
  • 接着执行 objdump -t 目标文件
    在这里插入图片描述

我们可以发现:
图中红框标出来的部分,即是命名倾轧的结果;
其中(以_Z3funi 举例):
①:_Z 是规定的前缀;
②:3 是函数名的字符个数(前面定义为fun);
③:fun 是函数名;
④:i 是参数列表中类型 i 的首字母。

不同系统和编译器的命名倾轧规则是不一样的

如何禁用呢?

我们都知道,C++是从C语言的基础上发展而来的,既然C语言不支持函数重载,那么C++在调用C语言的时候可能就会出问题,问题的关键就在于这个函数重载,把它禁用了就好。

如何禁用呢?

使用声明:extern "C" 的函数会禁止命名倾轧;
这样C++的函数就可以被C语言调用了。

通过查看一些C语言标准头文件,就可以发现其中有这个extern "C" ,表示不倾轧调用时的函数名。
在这里插入图片描述

为了头文件可以同时被C++/C使用,通常把 extern "C"放在__cplusplus 条件的宏定义中。

For example:

#include <iostream>
#include <string.h>
using namespace std;

extern "C"{
    void func(int a){cout<<"a = "<<a<<endl;}
    void func(int a,double b){cout<<"a = "<<a<<endl;}
}

int main(void){
    int a = 10;

    func(a);
    return 0;
}

这样的代码是不能够编译通过的,因为不倾轧的话就会使得两个函数的函数名一样,产生了重名。要想让上述代码正常调用,必须使用命名倾轧,做法如下:

#include <iostream>
#include <string.h>
using namespace std;
//倾轧就不会重名
void func(int a){cout<<"a = "<<a<<endl;}
void func(int a,double b){cout<<"a = "<<a<<endl;}

int main(void){
    int a = 10;

    func(a);
    return 0;
}

参考资料

【1】Sunrise. C++函数重载及原理(命名倾轧name mangling). CSDN. 2020-6-13
【2】Apollon_krj. C++函数重载与重载原理:命名倾轧. CSDN. 2017-03-07
【3】重载函数(百度百科)

TO BE CONTINUED…
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值