一、为什么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的程序里面去: