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"声明的更多相关文章

  1. paip.编程语言方法重载实现的原理及python,php,js中实现方法重载

    paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...

  2. 【C++初学者自学笔记二】函数重载(模块一)

    1.概念:同意作用域的一组参数列表不同,函数名相同的函数,这组函数叫函数重载(C语言是不能定义相同名称的函数,但是C++可以允许定义). 2作用:重载函数通常来命名一组功能相似的函数,这样做减少了函数 ...

  3. Javascript函数重载,存在呢—还是存在呢?

    1.What's is 函数重载? );//Here is int 10 print("ten");//Here is string ten } 可以发现在C++中会根据参数的类型 ...

  4. C++学习笔记之模板(1)——从函数重载到函数模板

    一.函数重载 因为函数重载比较容易理解,并且非常有助于我们理解函数模板的意义,所以这里我们先来用一个经典的例子展示为什么要使用函数重载,这比读文字定义有效的多. 现在我们编写一个交换两个int变量值得 ...

  5. 【C++】C++函数重载的总结

    函数重载: 出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重载函数(overloaded function).一定要注意函数重载的两个关键词:形参列表和作用域. 任何程序有且仅有 ...

  6. 0607pm克隆&引用类&加载类&面向对象串讲&函数重载

    克隆class Ren{ public $name; public $sex; function __construct($n,$s) { $this->name=$n; $this->s ...

  7. 深入浅出TypeScript(3)- 函数重载和泛型

    面向对象特性中,最根本的就是面向对象的三大基本特征:封装.继承.多态.同时,TypeScript中也存在多态的使用,比如函数重载,今天我们先看一下函数重载以及泛型的概念. 什么是函数重载 简单来说,函 ...

  8. python中不需要函数重载的原因

    函数重载主要是为了解决两个问题: 1.可变参数类型 2.可变参数个数 并且函数重载一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函 ...

  9. 在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”

    首先,作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用. 通常,在模块的头文件中对本模块提供给其它模块 ...

随机推荐

  1. ConcurrentHashMap源码解析

    转自:http://www.iteye.com/topic/344876 ConcurrentHashMap是Java 5中支持高并发.高吞吐量的线程安全HashMap实现. 实现原理 锁分离 (Lo ...

  2. 随笔-关于公网IP无法访问服务器的解决办法

    笔者的环境: windows server 2008 r2 .IIS,php,MySql. 理论上来讲,服务器,其实就是一个大型计算机,我们通过访问服务器的某个端口请求某个资源. 正常情况下,如果没有 ...

  3. Unity使用Mono.Xml代替System.Xml 测试

    测试环境 操作系统:Windows8.1 开发工具:Unity5.5.2 1.新建一个测试项目,观测引用System.Xml与Mono.Xml解析文件正确性,与打包后APK体积大小. 2.Mono.X ...

  4. OpenCV探索之路(十):图像修复技术

    在实际应用中,我们的图像常常会被噪声腐蚀,这些噪声或是镜头上的灰尘或水滴,或是旧照片的划痕,或者是图像遭到人为的涂画(比如马赛克)或者图像的部分本身已经损坏.如果我们想让这些受到破坏的额图片尽可能恢复 ...

  5. EntityFramework6.X 之LocalDB&ConnectionString

    LocalDB 面向开发人员的SQL Server Express的执行模式,它的安装将复制启动SQL Server数据库引擎所需的最少文件集且使用特定连接字符串来启动连接,它是可以创建和打开SQL ...

  6. Tomcat 部署项目的三种方法

    1.下载 Tomcat 服务器 ①.官网下载地址:http://tomcat.apache.org/ ②.tomcat 8.0 64位百度云下载地址:http://pan.baidu.com/s/1s ...

  7. 013 session_flush

    在hibernate中也存在flush这个功能,在默认的情况下session.commit()之前时,其实执行了一个flush命令. Session.flush功能: ②理缓存: ②执行sql(确定是 ...

  8. ELK安装与配置

    ELK介绍 日志主要包括系统日志.应用程序日志和安全日志.系统运维和开发人员可以通过日志了解服务器软硬件信息.检查配置过程中的错误及错误发生的原因.经常分析日志可以了解服务器的负荷,性能安全性,从而及 ...

  9. python之路 socket,socketsever初探

    socket的英文原义是"孔"或"插座".作为BSD UNIX的进程通信机制,取后一种意思.通常也称作"套接字",用于描述IP地址和端口,是 ...

  10. DDD理论学习系列(4)-- 领域模型

    DDD理论学习系列目录 1.引言 我们还是先来拆词理解,领域模型可以拆为"领域"和"模型"二词. 领域:按照我们之前的文章的理解,DDD中的领域是指软件系统要解 ...