问题引出:
C++允许在同一范围中声明几个功能类似的同名函数,但是这些
同名函数的形式参数(指参数的个数、类型或者顺序)必须不同
我们已知,编译器在编译代码时,会生成符号表,对于同名函数,进行函数重载时,编译器是如何处理它们,让代码可以顺利编译的呢?
讨论:
例子:
void fun(int x){}
void fun(double x){}
int fun(float x){return 0;}
void fun(int x,double y){}
这里有四个同名函数,对它们进行编译,查看.map文件,得到如下信息:
0002:00002ca0 ?fun@@YAHM@Z 00413ca0
0002:00002cd0 ?fun@@YAXH@Z 00413cd0
0002:00002d00 ?fun@@YAXHN@Z 00413d00
0002:00002d30 ?fun@@YAXN@Z 00413d30
可以看到,不同的fun函数,编译时是区别对待的:
1.符号表中的函数名包含了:函数名,函数返回值类型,函数参数类型。
经过观察,可以发现 “?…@@YA…@Z”可能是该编译器在处理函数重载时的通用格式,其中第一个省略号处存放原函数名,第二个省略号处放置参数类型、返回值类型(返回值类型在前)对应的字母。
字母对应关系(目测得出,仅供参考)
- int————H
- char———D
- void———X
- double——N
- float———M
- long———J
- long long—_J
- int*,char*……..——PAH,PAD……..
2.不同的同名函数分配了不同的地址空间。
由此可以大致的看出c++在处理函数重载时的实现方法。
解析面试题:在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?
先看c语言编译器对c语言中函数的处理:
例:对于函数
int fun1()
{
return 0;
}
void fun2(char*p)
{}
编译后得到:
0002:000003b0 _fun1 004113b0 f
0002:000003e0 _fun2 004113e0 f
可以看出,这里只存放了原本的函数名,并不会将函数参数、返回值类型等信息附加到函数明上。
在c++中调用被 C 编译器编译后的函数,因为编译器在处理函数时使用的方法不同,c语言中函数在编译后不符合c++的编译机制,加 extern “C”声明,使得c++编译器在处理这一块函数时使用c的方法。