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

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


相关推荐

  • django url标签_未指定url怎么解决

    django url标签_未指定url怎么解决前言当我们访问网页的时候,后台返回列表中有n条数据,此时我们会使用分页,比如一页只展示10条,但是我们访问第一页的时候大多数情况下,都会给url一个默认值,访问的时候直接展示第一页数据案例我们的

    2022年7月29日
    3
  • windows如何在局域网下共享文件(传输文件、修改文件)

    windows如何在局域网下共享文件(传输文件、修改文件)前些天在了解Git版本控制的时候,看到了“局域网下可以共享文件(阅读or修改)”。发现自己之前都没了解过这个,虽然用着GitHub却对其来源的变化不甚了解。于是就动手操作了一下windows如何在局域网下共享文件。对,还有一些局域网下的传输软件。但我还没有去了解,所以在这里先不说了。什么是局域网局域网(LocalAreaNetwork,LAN),又称内网。指覆盖局部区域(如办公室…

    2022年5月4日
    206
  • allowMultiQueries=true_python的list用法

    allowMultiQueries=true_python的list用法消息列表:消息 描述 WM_NOTIFICATION_CLICKED 控件被点击 WM_NOTIFICATION_RELEASED 控件被释放 WM_NOTIFICATION_MOVED_OUT 控件被点击,指针移出控件但没被释放 WM_NOTIFICATION_SEL_CHANGED 控件选中的内容被改变 常用函数LISTWHEEL_A…

    2022年10月8日
    0
  • pyhcarm激活码破解方法

    pyhcarm激活码破解方法,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月15日
    126
  • checkbox(复选框)和radio(单选按钮)的区别与详解

    checkbox(复选框)和radio(单选按钮)的区别与详解选中和取消选中一个复选框后,再次点击它,即可取消选中选中一个单选按钮后,再次点击它,不能取消选中&amp;amp;amp;amp;amp;amp;lt;!DOCTYPEhtml&amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;lt;htmllang=&amp;amp;amp;amp;amp;quot;en&amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp

    2022年5月7日
    154
  • OnTouch关于performClick的Warning

    OnTouch关于performClick的WarningOnTouch关于performClick的Warning当你对一个控件(例如FloatingActionButton)使用setOnTouchListener()或者是对你的自定义控件重写onTouchEvent方法时会出现这个警告,警告内容全文如下IfaViewthatoverridesonTouchEventorusesanOnTouchListenerd…

    2022年6月16日
    30

发表回复

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

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