C++函数重载实现的原理以及为什么在C++中使用用C语言编译的函数时,要在函数名称前面加上extern "C"声明
C++相对于C语言而言支持函数重载是其极大的一个特点,相信在使用C语言的时候大家如果要写一个实现两个整型数据相加的函数还要写一个浮点型数据相加的函数,那么这两个函数的名字绝对不可以一样,这样无疑在我们使用这个函数的时候增加了复杂性,但是在C++中我们却可以很好的解决这个问题,因为在C++中函数是支持重载的也就是说两个函数的函数名可以一样,这样并不会出现函数名重定义的问题,但是我们在使用的时候也要遵守一些规定,这些规定我们会在接下来的讨论中提到,下面我们就来分析在C++中函数是如何实现函数的重载的。
在这里我们用C语言和C++分别写两个函数,通过函数的符号表来观察函数名在经过编译之后究竟是什么形式的
下面就是我们的测试代码:
#include<iostream>
using namespace std;
int Add(int x, int y)
{
int z = ;
z = x + y;
return z;
}
double Add(double x, double y)
{
double z = ;
z = x + y;
return z;
}
int main()
{
cout<<Add(,)<<endl;
cout<<Add(1.5,3.5)<<endl;
return ;
}
在VS2008的编译环境下:
我们生成.map文件,然后可以查看函数在经过编译之后的函数名称为下图所示:

不难发现上图中函数命名的一些规律(当然这个规律只是片面的针对于VS2008编译环境):
1.以“?”开始和以”@Z”结尾
2.函数的名称紧接“?”之后
3.在函数明德后面分别是函数返回值类型修饰符、参数列表中的参数的类型修饰符
下面我们把这个相同的函数改为c语言的代码
代码如下:
//#include<iostream>
//using namespace std;
#include<stdio.h>
int Add(int x, int y)
{
int z = ;
z = x + y;
return z;
}
double Add(double x, double y)
{
double z = ;
z = x + y;
return z;
}
int main()
{
//cout<<Add(1,3)<<endl;
//cout<<Add(1.5,3.5)<<endl;
return ;
}
这时我们编译的话就会出现错误:

这里告诉我们函数名出现重定义
那么这是为什么呢?
这时我们注释掉一个函数然后编译后查看.map文件,查看函数重命名之后的名称

这里我们可以发现函数在编译之后重命名的名称仅仅只是在函数名称的前面加上了一个"_"(下划线),这样我们就不难分析了,C和C++编译的时候对函数的重命名机制是完全不一样的
1.C语言中仅仅只是在函数的名称的前面加上了"_"(下划线)
2.C++有自己的命名修饰规则,他会根据函数的参数列表中变量的类型等进行相应的类型修饰
虽然C++支持函数的重载但是我们在使用的时候也要注意以下几点:
1.函数的重载只是出现在同一作用域,例如假如两个工程里的函数名称相同,但是他们也不是函数的重载
2.函数名相同,函数的参数列表不同,返回值可同可不同,为什么函数返回值可同可不同呢?
这是因为在不同的编译环境下对于函数名称的修饰并不是相同的,下面就是在Linux环境下函数编译后重命名的形式:

仔细观察不难发现在Linux环境下的函数重命名的一些规则:
1.以“_Z”z作为开头,紧随其后的数字是函数名称的单词的个数
2.函数的名称后面有函数的参数列表中参数的类型修饰符,i是int型,d是double型
通过以上的阐述相信大家可以对C++中为什么可以实现函数重载有了清晰的认识,那么我们也就不难回答为什么在C++中调用被C编译过后的函数应该在前面加上 extern "C" 声明了。
这是因为我们当前是处于c++语言环境,这个时候我们如果不指定要调用的那个函数是用C语言编译的函数,那么当前在C++文件中编译时就会报错说是该函数是一个无法解析的外部符号,因为在编译运行的时候我们当前的程序会从符号表中去找相应的函数名,可是C++和C编译后生成的符号表中函数的名是不同的,那么这个函数也就是一个无法解析的外部符号了,但是当你用extern “C” 指明该函数是用C语言编译的函数,那么当前代码在编译运行的时候就会从用C语言编译的那个符号表文件中去查找相应的函数名,这样整个程序的编译运行费也就没有问题了。
C++函数重载实现的原理以及为什么在C++中使用用C语言编译的函数时,要在函数名称前面加上extern "C"声明的更多相关文章
- paip.编程语言方法重载实现的原理及python,php,js中实现方法重载
paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...
- 【C++初学者自学笔记二】函数重载(模块一)
1.概念:同意作用域的一组参数列表不同,函数名相同的函数,这组函数叫函数重载(C语言是不能定义相同名称的函数,但是C++可以允许定义). 2作用:重载函数通常来命名一组功能相似的函数,这样做减少了函数 ...
- Javascript函数重载,存在呢—还是存在呢?
1.What's is 函数重载? );//Here is int 10 print("ten");//Here is string ten } 可以发现在C++中会根据参数的类型 ...
- C++学习笔记之模板(1)——从函数重载到函数模板
一.函数重载 因为函数重载比较容易理解,并且非常有助于我们理解函数模板的意义,所以这里我们先来用一个经典的例子展示为什么要使用函数重载,这比读文字定义有效的多. 现在我们编写一个交换两个int变量值得 ...
- 【C++】C++函数重载的总结
函数重载: 出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重载函数(overloaded function).一定要注意函数重载的两个关键词:形参列表和作用域. 任何程序有且仅有 ...
- 0607pm克隆&引用类&加载类&面向对象串讲&函数重载
克隆class Ren{ public $name; public $sex; function __construct($n,$s) { $this->name=$n; $this->s ...
- 深入浅出TypeScript(3)- 函数重载和泛型
面向对象特性中,最根本的就是面向对象的三大基本特征:封装.继承.多态.同时,TypeScript中也存在多态的使用,比如函数重载,今天我们先看一下函数重载以及泛型的概念. 什么是函数重载 简单来说,函 ...
- python中不需要函数重载的原因
函数重载主要是为了解决两个问题: 1.可变参数类型 2.可变参数个数 并且函数重载一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函 ...
- 在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”
首先,作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用. 通常,在模块的头文件中对本模块提供给其它模块 ...
随机推荐
- ER模型的学习
(计应154兰家才)在建立表后开始了学习的第一步,了解数据库的基本知识,就以建立bbs论坛为标准学习er模型,首先建立了4个表分别是BBSReply,BBSSection,BBSTopic,BBSUs ...
- Azure Event Hub 技术研究系列2-发送事件到Event Hub
上篇博文中,我们介绍了Azure Event Hub的一些基本概念和架构: Azure Event Hub 技术研究系列1-Event Hub入门篇 本篇文章中,我们继续深入研究,了解Azure Ev ...
- xpo-4大类
Xpo (XPBaseObject.XPLiteObject.XPCustomObject.XPObject) 类名 延后删除 是否乐观锁定 提供OID字段 XPBaseObject 不支持 支持 ...
- JS执行事件
先贴出几个名词: 同步任务: 在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务 异步任务: 不进入主线程,而进入"任务队列"的任务,只有任务队列通知主线程, ...
- 【JAVAWEB学习笔记】14_response
HttpServletResponse 学习目标 案例一.完成文件下载 案例二.生成验证码(了解) 1.HttpServletResponse概述 我们在创建Servlet时会覆盖service()方 ...
- 使用windows桌面ftp上传文件到linux服务器
首先在linux服务器上安装ftp [root@host2 test]#yum -y install ftp vsftpd [root@host2 test]#service vsftpd start ...
- 关于MySQL数据库的一些操作
启动:net start MySQL 关闭:net stop MySQL (也可以用quit:) 登录到MySQL:mysql -u root -p -u : 所要登录的用户名; -p : 告诉服务器 ...
- WinForm笔记
Hi All, 分享一个学WinForm时的笔记: 1. 关键字 partial:是部分类,允许将一个类放在多个文件当中. 2. MessageBox()类相当于Console.WriteLine() ...
- Docker手动配置Lamp镜像
自从接了学长布置的任务,自学Docker也学了很久了,先整一个Lamp出来吧 在Docker Hub上找了很多Lamp的镜像 网上都说tutum的镜像做的还是不错的 试试 折腾了一上午无果... 算了 ...
- AngularJS语法基础及数据绑定——详解各种数据绑定指令、属性应用
AngularJS简单易学,但是功能强大.特别是在构建单页面应用方面效果显著.而 数据绑定 可以说是他被广泛使用的最主要的优点.他舍弃了对DOM的操作方式,一切都由AngularJS来自动更新视图,我 ...