C++为什么支持重载?externC有什么用?从编译链接的过程中就可以找到答案,首先聊一聊编译链接的过程
总共分为四个过程——预处理,编译,汇编和链接。
1.预处理--它做的主要是头文件展开、宏替换、条件编译、去掉注释等工作。预处理结束后,会生成预编译文件(.i)
2.编译--这个阶段会检查语法,将经过预处理后的预编译文件转换成特定汇编代码,生成汇编文件(.s)
3.汇编--将编译阶段生成的汇编文件转化成机器码,生成可重定位目标文件(.o/.obj)。
4.链接--将多个目标文件连接成最终可执行目标文件(.out/.exe)。有些文件里面调用的函数只有声明,函数的定义是在另一个文件中定义的,这个时候就需要通过这个过程根据函数的地址将其链接起来。
那么C++为什么支持重载呢?
编译的过程中会生成一个符号表将对应的函数名和函数的地址映射起来,这样在链接的时候就可以根据函数名找到对应函数的地址并将其链接起来。
在c++中,函数名在编译后会根据相应的函数名修饰规则修饰,即使函数名相同,只要函数的参数数量,参数类型,参数顺序不一样,修饰后的函数名就不一样,这样链接的时候也可以根据修饰后的函数名找到对应的函数地址进行链接。
但是在c语言中,编译后的函数名就是原来的函数名,所以如果函数名相同,编译就会报错。
externC有什么用?
在我们调用库的时候,c++可以调用c++的库,c可以调用c的库
实际上,c++中也可以调用c的静态库和动态库,c中也可以调用c++的静态库和动态库
由于C和C++编译器对函数名字修饰规则不同,可能就会导致链接失败,因为链接的时候会根据符号表中的函数名和对应的地址,将其链接起来,c++在编译的时候对函数名的修饰规则是不一样的,就算是同样的函数名,参数类型不同,函数的修饰名也会不同,c语言是直接原模原样复制下来的。两者对函数名的修饰方式不同。
在该种场景下,就需要使用extern "C"。在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。
如果是c调用c++的库,那就在c++库中加上extern C,按照C的函数修饰规则去编译,但是不能这样子直接加,这样c++库这边可以编译通过,但是当这些函数在头文件里面展开的时候就会出错,因为展开后再c的环境中,c语言不认识externc,这是c++的语法。
这个时候可以使用条件编译+宏的方式来解决,如图所示。这样在c++库这边有加externC,编译的时候函数是按照C语言规则来编译的。当里面的内容展开到c的文件里面的时候,条件编译会将externC去掉,所以c语言编译也能够通过,这样就可以成功调用了。