函数模板与同名的非模板函数不可以重载(重载的定义)

关于函数的重载机制,是一个比较复杂的问题,其中涉及到了优先级定义和最佳匹配等问题,如果要阐述清楚,恐怕不是一两篇文章就能说的明白。但是如果掌握了一些常用的“规律”,对于了解程序对重载函数是如何进行选择也有很大的好处,本文尝试将自己理解的知识,结合下面简单的例子简略的说说函数重载机制,文章的摘录部分列出了一些关于程序如何选择重载函数的规则。:)例子如下:#include

大家好,又见面了,我是你们的朋友全栈君。

关于函数的重载机制,是一个比较复杂的问题,其中涉及到了优先级定义和最佳匹配等问题,如果要阐述清楚,恐怕不是一两篇文章就能说的明白。但是如果掌握了一些常用的“规律”,对于了解程序对重载函数是如何进行选择也有很大的好处,本文尝试将自己理解的知识,结合下面简单的例子简略的说说函数重载机制,文章的摘录部分列出了一些关于程序如何选择重载函数的规则。: )

例子如下:

#include <iostream>

 

//non-template function

inline const int& max( const int& a, const int& b )

{

std::cout << “non-template max() is called” << std::endl;

return a < b ? b : a;

}

 

//template function

template < typename T >

inline const T& max( const T& a, const T& b )

{

std::cout << “template max() is called” << std::endl;

return a < b ? b : a;

}

 

int main()

{

::max( 7.0, 42.0 ); //template max() is called

::max( ‘a’‘b’ ); //template max() is called

::max( 7, 42 ); //non-template max() is called

::max<>( 7, 42 ); //template max() is called

::max< double >( 7, 42 ); //template max() is called

::max( ‘a’, 42.7 ); //non-template max() is called

}

程序顺利通过编译,并运行得出结果,说明同名的非函数模板函数和函数模板可以共存。程序会通过优先级和最佳匹配的方式从候选的重载函数集中选定一个函数进行调用(所遵循的规则见后面的摘录部分)。

程序的输出结果见每个函数调用的注释,对于第一和第二个输出结果想必应该没有太多的疑问,程序调用的是函数模板max,下面主要分析其余的输出。

【一】、max( 7, 42 );调用的是非函数模板max()。当其它的要素都相等时,重载机制将优先选择调用非函数模板而不是函数模板【对于这个问题,个人觉得可能是基于如下的原因:进行重载将降低程序的效率,对非函数模板是如此,对于更为复杂的函数模板更是如此(至少还需进行一次实例化),因此重载机制将优先选择调用非函数模板而不是函数模板。】。那些无法跟非函数模板进行最佳匹配的,则调用函数模板的实例化对象,如第一和第二个函数调用。

【二】、max<>( 7, 42 );max( 7, 42 );的唯一区别是前者多了一个模板参数列表,还记得前面笔记中说到的函数模板参数的问题么?<>中的参数用于指定函数模板中,传入的参数类型跟返回值类型,列表中参数的顺序对应于模板中声明的类型的顺序。这里的参数列表为空,但却告诉了编译器,这个函数只在函数模板中选择最佳匹配的函数调用。同样的,max< double >( 7, 42 ); 调用的是函数模板的一个实例化对象,这里指定了模板参数的类型,因此对于传入的值,程序会对其进行一个转换(从int转为double),然后比较大小。

【三】、对于最后一个函数调用max( ‘a’, 42.7 );一开始我认为是调用非函数模板,结果确实也是调用了非函数模板,我的理由是两个参数的类型明显不同,后面看到书上的解释,是这么说的:自动类型转换,只适用于一般函数(即非函数模板)。其实我的理解也没有什么偏差,只是不够深刻。如果觉得‘a'(char)42.7(程序默认为double)相差太大,不好理解上面那句话,试一下这个调用max( ‘a’, 42 );(一般我们都会对charint划上一个隐式的等号,默认char就是int的子集,但事实上还是要经过一个隐式的转换)结果也是调用了非函数模板max()

 

//====================【附录:关于重载的一些说明】====================

这部分的内容主要摘自《c++template》中的附录,有少许语言组织上的改动。另外,《c++primer》中对重载也有比较详细的讨论。

【一】何时会进行重载?

首先,如果是通过函数指针或者成员函数指针来进行调用,就不会进行重载解析,因为究竟调用的是哪个函数是在运行期由指针(实际上所指向对象)来决定的。其次,类似函数的宏不能被重载,因此也不会进行重载解析。

【二】重载是个什么样的过程?

  • 查找名称,从而形成一个初始化的重载集(合)。

  • 如果有必要,会用各种方法对这个集合进行修改(例如,发生模板演绎的时候)。

  • 任何与调用不匹配(即使考虑了隐式转换和缺省实参之后仍然不匹配)的候选函数都从重载集中删除,最后得到的集合就是:可行的候选函数集。

  • 执行重载解析来寻找一个最佳候选函数。如果能找到,则选择这个最佳候选函数;否则,这个调用就是二义性的。

  • 检查这个被选定的最佳候选函数。例如,如果它具有不能访问的私有成员,则可能会给出诊断信息。

【三】关于上面的说到的重载解析,是根据什么原则来选定最佳候选函数?

  • 完美匹配。参数的类型和实参(表达式)的类型相同,或者参数的类型是指向实参类型的引用(也可以增加const或者volatile限定符)。

  • 有细微调整的匹配。如数组转变为指向数组第一个元素的指针,或者添加const,从而让类型为int**的实参匹配类型为int const* const*的参数等。

  • 发生提升的匹配。提升是一种隐式类型转换,它包含把占位少的整数类型(如boolcharshort或者某些枚举)转换为占位多的类型(如intunsigned intlong或者unsigned long),还包括从floatdouble的类型转换。

  • 发生标准转换(类型转换)的匹配。这包含任何种类的标准转型(如intfloat),但并不包含隐式调用的类型转换运算符和单参数构造函数

  • 发生用户自定义转换的匹配。这允许任何种类的隐式类型转换。

  • 和省略号的匹配。省略号参数可以匹配任何类型(但匹配非PODplain old data)类型会导致未经定义的行为)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/128449.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ubuntu 18.04 EM7345 4G 模块接入点删除「建议收藏」

    ubuntuEM7345创建多个接入点如何删除本人TinkPadT440P笔记本,装了ubuntu18.04,前几天一激动,买了一个M2接口的EM7345,支持联通3G/4G,电信4G,都能正常使用,我一不小心建了许动连接点,本人有洁癖,但又不知道怎么删除,后来找了好几天,找到以下路径,又这方面需求的同学,可以参考一下/etc/NetworkManager/syst…

    2022年4月12日
    181
  • 一文搞懂│http 和 https 的通信过程及区别

    一文搞懂│http 和 https 的通信过程及区别拨云见日,带你学好网络安全通信基础

    2022年8月16日
    9
  • linux安装yarn

    linux安装yarn这里介绍使用yum的方式:先要安装node.js,用node-v可以查看是否安装了node。1、添加yarn仓库wgethttps://dl.yarnpkg.com/rpm/yarn.repo-O/etc/yum.repos.d/yarn.repo2、安装yarnyum-yinstallyarn安装完成后,yarn-v可以查看版本。…

    2022年5月9日
    38
  • mt4历史数据下载位置_头榜土豪数据中心

    mt4历史数据下载位置_头榜土豪数据中心    打开MT4,按F2,会出现一个历史数据中心对话框。之前,我直接按下载按钮时,往往下载数据会出错。因此百度了很久,也查看了很多的处理方式,觉得都不尽如人意。不是数据找不到,就是即使找到了下载时也出现问题。    近日又捣弄了一番,跑到MT4中的history文件夹,发现里面有各个我以前申请的模拟帐户,而且是不同公司下的帐户。这突然让我意识到,我在历史数据中心对话框中点击下载时出现的警

    2022年8月15日
    7
  • VS中时间控件的使用[通俗易懂]

    VS中时间控件的使用[通俗易懂]使用方法:1.下载时间控件 My97DatePickerBeta.2.在VS中新建项目,添加web窗体。3.将下载好的文件导入你的项目文件中,然后添加如下代码: &lt;scriptsrc="Content/My97DatePickerBeta/WdatePicker.js"type="text/javascript"&gt;&lt;/script&gt;//引号内为Wdat…

    2022年5月24日
    133
  • 怎么用python打开csv文件_Python文本处理之csv-csv文件怎么打开[通俗易懂]

    怎么用python打开csv文件_Python文本处理之csv-csv文件怎么打开[通俗易懂]csv英文全称是Comma-SeparatedValue,字面翻译逗号分隔值,是一种常见的文本格式文档,可用Excel打开,也可用常见的文本编辑器打开。csv文件经常用于在电子表格软件和纯文本之间交互数据。Python内置了csv模块,可以很方便的操作csv文件。下面介绍两种读写csv文件的方法。一、通过reader和writer函数先看一段简单的示例代码:text包含两个列表元素,首先把这两行…

    2022年7月21日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号