【C++】函数重载的底层原理

一、为什么C++有重载,而C语言没有呢?

我们需要从程序的编译、链接的角度去分析,我们要知道编译的各个阶段大致在做什么。

预处理:宏替换,头文件的展开,注释删除等文本操作。生成.i文件

编译:进行语法错误的检测,生成.s汇编文件

汇编:将汇编文件转换为机器码,生成.o二进制文件

链接:将汇编生成的文件合并,并链接其他库生成可执行文件

我们先直接说结论:C++之所以会有重载,是因为它的函数名修饰规则不同。

假设有如下代码:

它的编译过程是这样的:

 图中我们可以看到,预处理,编译,汇编都不涉及其他文件,只是对自己进行编码操作。

我们再用看看另外一个例子,我们查看代码的汇编指令,我们在生成的汇编指令中看到,用call声明了函数fun1和fun2,并加上了这两个函数的地址。目前为止我们只需明确,在链接后的文件中,call指令声明了函数,且带上了函数的地址。 

 为了方便一步一步的观察链接时的编译操作,我们使用Linu环境进行操作:

我们分别使用gcc,g++编译,查看它的func.o文件

 图中红字部分只是为了提前将结论写出。

这里我们就可以得出一个结论,就是C++和C生成的符号表中,函数名的修饰规则是不同的,C++是函数名加参数类型,C就是函数名本身。也就是说C++中的同名函数重载,在底层来看其实是两个函数符号。 我们再来看看编译器在链接阶段做的事情:

利用Linux编译环境,总结出来如下的图:

   test.o是带有main函数的目标文件,可以看到在还没有进行链接时,call声明的函数,只给了函数一个声明,还没有将函数的地址赋值过去。我们再将链接后的文件打开:

 

 可以看到链接后的文件call将函数符号和地址都给了出来,这里我们就可以得出链接阶段除了将文件合并外,还会找只给声明的函数的地址

下图我画出了C++和C的链接图

 

最后我们的核心:C++之所以有重载,其原因是函数名修饰规则不同 

二、C++程序调用C库

先设置C程序输出方式

 

 

 找到生成的静态库.lib文件

 到C++的程序里去

 最后阶段,C++是由C衍生出来的,但两者的函数名修饰规则不同,所以我们需要告诉C++我们使用的是C库,让他使用C的方式去编译它。

 包含C库的头文件,再使用extern “C”声明我们使用的是C库,需要用C语言的方式去编译链接。

三、C程序调用C++库

先修改C++的输出方式

 我们需要明确C++是了解C的所以可以使用extern "C"声明,但是C是不认识C++的。

所以我们还需要修改一部分C++程序,使其符合C的规则:

 

找到生成的静态库文件 ,再到C的程序里面去:

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

绅士·永

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

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

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

打赏作者

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

抵扣说明:

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

余额充值