重载 — c++ name mangling

在c++ 中,众所周知,为了和c语言向下兼容,c++做出了很多的牺牲和让步,在这里面,函数,比c语言中的函数更要复杂和麻烦。

c语言中的函数是不具有重载的,所以函数名即名字,在编译链接时,若是两个文件中有重复的名字最多报一个错误而已,而c++中,却多出了不少问题:

普通函数重载

首先,拥有的函数重载,重载的名称问题。

拥有了一些东西,你也失去了一些东西。

int foo() {}
int foo(int x) {}

int main() {
  std::function<int(int)> f = foo;
  return 0;
}

试试看上述代码是否可以编译通过,若是不行,如何改正?

重载给我们带来了一种假象,让我们可以传不同的参数进去然后转发到不同的函数去执行。

看着很美好,其实并不是那么的美妙。

先看看c++的重载是如何做的吧!

现在我们有一个不重载的函数:

在这里插入图片描述

nm来看看其名字是如何的:

现在,nm告诉我们,这个函数的名字叫做 _Z4testv

多写几个函数试试:

在这里插入图片描述

nm看看结果

在这里插入图片描述

发现,名称其实还是有一些规律,

_Z4为前缀,参数名其后依次排序(g++里面int参数名是i,double是d)

可以使用c++filt来进行解析名称

在这里插入图片描述

那么,我们可以就直接用这个名称进行调用吗?

讲道理,在汇编层面,我觉得是可以的,来试试看

先看看汇编上的名字是不是刚才那样的名字

在这里插入图片描述

c++也遵循c语言的abi,所以,按理来说,c语言可以直接链接c++编译出来的二进制文件

现在我们的c语言调用代码如下:

在这里插入图片描述

可以发现,我们只是简单的声明了一下即可,为了链接地址所用

现在将 c文件编译,然后和c++的这个demo文件进行链接

在这里插入图片描述

在这里插入图片描述

然后,我们就可以对这个名字直接进行调用


归根结底,其实我们发现,c++重载无非就是进行名称重写罢了,没什么稀奇的。

但是,有时候,重载却会给你带来一些坑

比如下列代码:

#include <stdio.h>
void fun(int) {
  printf("fun int\n");
}

void test() {
  fun('a');
}

void fun(char) {
  printf("fun char\n");
}
int main() {
  test();
  return 0;
}

你觉得应该是输出什么呢?

反正在我的机器上输出的是 fun int

我机器是编译器是:gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)

成员函数or命名空间内函数重载

那么,上面说了普通函数的重载,成员函数重载又是什么样子呢?

在这里插入图片描述

nm 打印出来是这个样子的:

在这里插入图片描述

可以看到,这个名字为什么和普通重载的不一样呢?

那么,命名空间内的函数重载形式是什么样子呢?

在这里插入图片描述

在这里插入图片描述

_ZN4Demo3funEi很好分析,意思是 4 Demo 3 fun,前面的命名空间是Demo,然后是Demo下的fun函数

数字用于分割参数与函数名之间的区别


题外话

若是c语言要调用c++现有内容,如何做呢?

正规做法: 采用 extern "C"的表示来不让起进行 name mangling

不正经的做法:c语言用已有c++库如何做呢,此时c++并没有兼容c的想法,意思是c语言很尴尬的调用不到同名的函数,因为被重载掉了,找出 name mangling 后的函数名,手动构造所需参数进行调用(自己玩玩就好了,不能真的用在实际中)

[amjieker]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值