初识C++之函数重载

最近开始学习C++,了解到它在C语言没有的一个特性 – 函数重载,这一特性使得c++的函数数量得以减少,减小了对名字空间的污染,另外对程序的可读性也有很大帮助。

那么c++的函数重载这一特性是怎么实现的,为什么不会发生命名冲突呢?别的函数在调用这些函数时编译器是怎么解析的呢?怎么知道它该调用哪一个函数呢?下面就这些问题来做一些简单解析。

1、什么是函数重载

C++允许在同一作用域内声明并实现几个名称相同,功能相似的函数,但必须保证这些函数的参数列表不同(参数个数不同、参数类型不同或者参数顺序不同)

根据上面的定义,判断哪些是正确的函数重载,哪些是错误的:

int Add(int a, int b)
{return a + b;
}double Add(double a, double b)
{return a + b;
}

double Add(double a, int b)
{return a + b;
}double Add(int a, double b)
{return a + b;
}

int Add(int a, int b)
{return a + b;
}int Add(int a, int b, int c)
{return a + b + c;
}

double Add(int a, double b)
{return a + b;
}double Add(int b, double a)
{return a + b;
}

int Add(int a, int b)
{return a + b;
}double Add(int a, int b)
{return a + b;
}

①②③很容易得出都是正确的函数重载;
④乍一看,很像是满足了参数顺序不同这一条件,但仔细分析一下,函数在定义或声明是是可以省略参数名的,因为编译器只检查函数参数的类型与个数,并不会检查函数名。那么,④的两个函数就可以看做是一个,因为它们无法构成函数重载;
⑤看起来也很像啊,但它满足函数重载的任何要求了吗,另个函数参数列表完全是一样的,唯一不一样的就是函数的返回值不同,但仅仅返回不同是无法构成函数重载的的,因此,它们也无法构函数重载。

2、为什么需要函数重载

想一想我们的C语言里是怎么定义不同类型的数据的加法函数的:

int Add(int a, int b); –> int 型数据的加法函数
short Add(short a, short b); –> short 型数据的加法函数
double Add(double a, double b); –> double 型数据的加法函数

是不是感觉很麻烦,都是同一功能的函数,却要起不同的名字,正式基于这一点,c++允许实现函数重载,这样不仅同一功能的函数都能叫同一名字,而且节省了名字空间。

3、编译器如何解决函数重载的命名冲突

c++确实能支持函数重载,但编译器是怎么处理这种特性,使它们在编译后不会出现名字冲突的呢?

这里可以参考我的另一篇博客:
重载函数编译后的新名字
http://blog.csdn.net/ljx_5489464/article/details/50981773

4、编译器如何解析重载函数的调用呢?

上面我们知道了,编译器通过一定的机制使重载函数在编译后不会发生名字冲突,那么在调用这些重载的函数时,编译器是如何知道该调用哪一个的呢?

编译器一般需要依次按照下列规则来判断:
a. 精确匹配:参数列表完全匹配,或者只是做微不足道的转换,如数组名到指针、函数名到指向函数的指针、T到const T;
b. 提升匹配:即整数提升(如bool 到 int、char到int、short 到int),float到double
c. 使用标准转换匹配:如int 到double、double到int、double到long double、Derived*到Base*、T*到void*、int到unsigned int;
d. 使用用户自定义匹配;
e. 使用省略号匹配:类似printf中省略号参数

通过以上规则来进行选择:
①根据函数名确定候选函数集
②确定可用函数
③确定最佳匹配函数

如果在最有多个最佳匹配函数找到,调用将被拒绝(因为有歧义、模凌两可)。

本文参考:
http://www.cnblogs.com/skynet/archive/2010/09/05/1818636.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

const在C与C++中的区别

1、const用于C –> 运行时常量 a. 修饰变量 修饰变量为常变量(只读变量) const int i 10; 此时i还是一个变量,不信你可以把它用来当作定义一个数组时的数组长度,一定会报错。不过它具有一种常属性,它的值一直都…

乱入的'\0'

看这个题之前,先来回忆一下strlen函数的工作机制: strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,…

强迫症的自我恢复

怎样克服强迫症?这是很多的人比较关注的一个问题。强迫症给人们的工作和生活带来很严重的影响,如果不及时进行治疗,对人的健康损害是很大的。那么怎样克服强迫症呢?下面就介绍一些怎样克服强迫症的调试方法,希望能帮助…

如何克服拖延症

拖延几乎成为现代人的通病,“先放一下,待会再行动”成为拖延者最大的思想毒瘤,如何积极地克服拖延症,已经成为了一个大课题。 1、正视自己的拖延症。 要改掉拖延症坏毛病,首先就是要正确认识到拖延症的危害&#xff…

初识C++之指针与引用

1、What a. 指针: 指针可以看做是一个特殊的变量,它是用来存放变量的地址值的。 b. 引用 引用的话,可以看做是给变量起的一个别名,而不是定义一个新变量,它与那个变量的本质是相同的,内容与地址都是一样…

初识C++之剖析const与#define

1、 编译器处理方式不同   #define是一个宏定义命令,它是在预处理阶段就进行了替换;   const修饰的是一个编译时常量,它是在编译阶段处理的。 2、 类型和安全检查不同   #define定义的标识符仅仅是产生文本替换,不管内容…

初识C++之运算符重载

C里面有一个叫作运算符重载的特性,它其实是基于函数实现的,下面就来介绍一下运算符重载。 1、What  C中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类…

对堆栈的认识

什么是堆和栈,它们在哪儿? 问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。我的意思是我理解什…

Waiting For Debugger

最近楼主在使用手机上的邮政银行时,总是打不开,要强制关闭,给我一个“Waiting For Debugger”的提示,相信朋友们应该遇到过类似的问题,当然这里不一定就是邮政银行出问题,可能是你手机里的任意一款软件&…

防止头文件重复包含之pragma once与#ifndef

在我们自己编写 C/C的头文件时,可能会忽略一点:用一些处理机制来避免头文件的重复包含,因为头文件的内容在预编译时是把头文件的内容完全拷贝到引入的地方替换头文件的包含命令,而包含的头文件可能有包含很多内容,所以…

初识C++之继承

1、何为继承 C中所谓继承,就是在一个已存在类的基础上创建一个新的类,新类获得已存在类的部分特性(为什么是部分特性,后面会讲到)。已存在类被称为基类(Base Class)或父类(Father Cl…

初识C++之函数重载、重写、重定义的区别

在C的学习中,慢慢接触了一些很容易混淆的名词,今天就来剖析几个容易混淆的名词。 1、函数重载   重载函数是函数的一种特殊情况,为方便使用,C允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参…

初识C++之封装

学习C不得不说到C的三大特性:封装、继承、多态,今天就先来剖析一下他的封装性。 1、什么是封装   封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进…

初识C++之虚函数

1、什么是虚函数   在基类中用virtual关键字修饰,并在一个或多个派生类中被重新定义的成员函数,用法格式为:   virtual 函数返回类型 函数名(参数表)    {     函数体    }    虚函数是实现多态性…

初识C++之多态

多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。 1、什么是多态   多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的…

从尾到头打印单链表(C语言)

void PrintListTailToHead(PSListNode pHead) {if (NULL ! pHead){//递归实现PrintListTailToHead(pHead->pNextNode);printf("%d ", pHead->data);} } 递归方式很容易就能实现。

删除一个无头单链表的非尾节点(C语言)

void DelNotTailNode(PSListNode pos) {PSListNode pNode NULL;assert(pos);if (NULL pos->pNextNode){return;}else{DataType temp 0;//交换pos和pos->pNextNode的数据(相当于交换了两个结点的位置),使问题转换为删除pos指向的结点…

在无头单链表的一个非头节点前插入一个节点(C语言)

①时间复杂度为N: void InsertNotHead(PSListNode pHead, PSListNode pos, DataType data) {PSListNode pPreNode pHead;PSListNode pPreNode pHead;if (NULL pos){return;}else{//先找到pos结点前面的结点while(pCurNode ! pos){pPreNode pCurNode;pCurNode …

单链表实现约瑟夫环(JosephCircle)(C语言)

//使链表形成一个环 void FormCyc(PSListNode *pHead) {if (NULL pHead){return;}else{PSListNode pNode *pHead;while (NULL ! (pNode->pNextNode)){pNode pNode->pNextNode;}pNode->pNextNode *pHead;} }PSListNode JosephCircle(PSListNode pHead, int M) {if …

逆置/反转单链表(C语言)

1、逆置链表:前插法 void ReverseList(PSListNode* pHead) {if (NULL *pHead){return;}else{//创建一个新的空链表,遍历pHead指向的链表里的所有节点,每找到一个,就前插到新链表里PSListNode pNewHead *pHead;*pHead (*pHead)…