您的位置:首页 > 编程语言 > C语言/C++

C++函数重载实现的原理以及为什么在C++中调用C语言编译的函数时要加上extern "C"声明

2017-07-13 17:04 627 查看
  C++相对于C语言而言支持函数重载是其极大的一个特点,相信在使用C语言的时候大家如果要写一个实现两个整型数据相加的函数还要写一个浮点型数据相加的函数,那么这两个函数的名字绝对不可以一样,这样无疑在我们使用这个函数的时候增加了复杂性,但是在C++中我们却可以很好的解决这个问题,因为在C++中函数是支持重载的也就是说两个函数的函数名可以一样,这样并不会出现函数名重定义的问题。

但是我们在使用的时候也要遵守一些规定,这些规定我们会在接下来的讨论中提到,下面我们就来分析在C++中函数是如何实现函数的重载的。

在这里我们用C语言和C++分别写两个函数,通过函数的符号表来观察函数名在经过编译之后究竟是什么形式的

下面是我的c++测试代码

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}

double Add(double x, double y)
{
double z = 0;
z = x + y;
return z;
}

int main()
{
cout<<Add(1,3)<<endl;
cout<<Add(1.5,3.5)<<endl;
return 0;
}



在vs2008里编译生成.map文件后,我们可以看到编译后的两个函数名称如下图所示



可以发现一些规律(ps:当然这些规律也仅仅是针对vs2008这个编译器而言的):

1.都是以“?”开头,以“@z”结尾

2.在“?”后紧跟自己的函数名

3.在函数名后面分别是函数返回值类型修饰符、参数列表中的参数的类型修饰符

下面我们把这个相同的函数改为c语言的代码

代码如下:
#include <stdio.h>

int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}

double Add(double x, double y)
{
double z = 0;
z = x + y;
return z;
}

int main()
{
/*cout<<Add(1,3)<<endl;
cout<<Add(1.5,3.5)<<endl;*/
return 0;
}
这个时候编译会出现如下错误:



这里告诉我们Add函数出现了重定义,这时我们注释掉一个函数然后编译后查看.map文件,查看函数重命名之后的名称



这里我们可以发现,c语言中,对于函数的重命名只是在函数名前加上一个“_”,因此,不难分析c++之所以实现了重载,是因为c和c++在编译时对于函数的重命名机制是不一样的

1.C语言中仅仅只是在函数的名称的前面加上了"_"(下划线)

2.C++有自己的命名修饰规则,他会根据函数的参数列表中变量的类型等进行相应的类型修饰

虽然C++支持函数的重载但是我们在使用的时候也要注意

函数的重载只是出现在同一作用域,例如假如两个工程里的函数名称相同,但是他们也不是函数的重载

通过以上的阐述相信大家可以对C++中为什么可以实现函数重载有了清晰的认识,那么我们也就不难回答为什么在C++中调用被C编译过后的函数应该在前面加上
extern "C" 声明了。

这是因为我么当前所处的环境为c++的环境,这个时候我们如果想使用c环境下编译的函数,如果不对他进行指定,那么在当前c++文件中编译时就会报错说该函数是一个无法解析的外部符号,因为在编译运行时,当前的程序会按照c++的符号表以及函数重命名的规则去寻找该函数,可是C++和C编译后生成的符号表中函数的名是不同的,那么这个函数也就是一个无法解析的外部符号了,但是当你用extern
“C” 指明该函数是用C语言编译的函数,那么当前代码在编译运行的时候就会从用C语言编译的那个符号表文件中去查找相应的函数名,这样整个程序的编译运行也就没有问题了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐