二义性调用(Ambiguous Call)
一天早上遇到的事物,下午又恰好看到了专业的补充,对此将其记录下来。
二义性调用(Ambiguous Call),属于一种编译错误。
在调用函数,去匹配合适的参数列表时,发现当前所提供参数,能匹配出多个重载函数。比如:
int add(int a, int b) { return a + b;
} template<typename T>
T add(T a, T b) { return a + b;
} int main() { add(10, 20); add(10.5, 20.5); add(string("10.5"), string("20.5"));return 0;
}
当然,编译器不会那么呆,会追求最佳匹配。当参数为两个 int
时,就会调用 add(int, int)
, 而不会是 add(T, T)
。
但是,若最佳匹配也存在多个的情况下,那么就不对劲了:
long long add(int, long long) { return 0;
} long long add(long long, int) { return 0;
} int main() { // ???add(10, 20); return 0;
}
对于字面量整数来说,完全兼容 int
与 long long
类型,于是就无法区分,到底要调用是哪一个函数,因为无论调用哪一个,都合情合理,从类型的角度来说完全没有问题。
对于
add(int, long long)
与add(long long, int)
所形成的的重构有点扯,但此处只是演示二义性问题,不探究严谨性。
最佳解决方案是:完全杜绝这种函数重构的产生。
否则,请在调用时,显式告诉编译器,该字面量值的类型具体是什么,而不要让其自行推测。比如:
long long add(int, long long) { return 0;
} long long add(long long, int) { return 0;
} int main() { // okint a = 10; long long b = 20; add(a, b); add((long long)10, 20); add(10, (long long)20); return 0;
}
其中发现,若是只标注任意一参数类型为 int
,依然会导致二义性调用,比较有趣,可以分析一下为什么。
int main() { // ???add((int)10, 20); add(10, (int)20); return 0;
}
若是显式说明其中一个参数为 int
,那么根据我们的观察,应该去选择函数签名为 int a, T b
或 T a, int b
的函数,来达成匹配。
然而对于整数字面量来说,一个默认行为就是,将其当作 int
进行处理,于是又回到了原点,int
都能无损转换为 long long
,那谁来转换。显式标注并不能参与转换优先级竞争。
只有当另一个未显式指定 int
类型的参数,其数值超过了 int
范围,那么才会将其定位至 long long
, 从而达成匹配。
正常情况下,是很难遇到二义性调用的,想要随手写出这种函数都很难,知道这样一个术语,用于描述这种状况即可。
End
二义性调用(Ambiguous Call)相关推荐
- C++ 函数匹配 重载函数的调用规则
学习<C++ Primer>一书中,函数匹配这一节内容信息较多,现截取重点内容记录于此.便于你对本文内容更好的理解,你需对类型提升.算术类型转换以及顶层cosnt,底层const有一定的了 ...
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
- 深入理解C++重载函数
深入理解C++重载函数 1.定义:C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数.类型或者顺序)必须不同,即函数的参数列表不同,也就是说用同一个运算符完成不 ...
- Scala入门到精通——第十八节 隐式转换与隐式参数(一)
本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...
- 《C++ Primer 5th》笔记(6 / 19):函数
文章目录 函数基础 局部对象 函数声明 分离式编译 参数传递 传递参数 传引用参数 使用引用避免拷贝 使用引用形参返回额外信息 const形参和实参 指针或引用形参与const 尽量使用常量引用 数组 ...
- ASP.NET文件夹
ASP.NET文件夹 1. Bin文件夹 Bin文件夹包含应用程序所需的,用于控件.组件或者需要引用的任何其他代码的可部署程序集. 该目录中存在的任何.dll文件将自动地链接到应用程序.如果在该文件夹 ...
- 【java】理解和运用Java中的Lambda
1.概述 转载:理解和运用Java中的Lambda 前提 回想一下,JDK8是2014年发布正式版的,到现在为(2020-02-08)止已经过去了5年多.JDK8引入的两个比较强大的新特性是Lambd ...
- [转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)...
以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...
- 编译原理_P1001
1 绝大部分软件使用高级程序设计语言来编写.用这些语言编写的软件必须经过编译器的编译,才能转换为可以在计算机上运行的机器代码.编译器所生成代码的正确性和质量会直接影响成千上万的软件.虽然大部分人不会参 ...
- 编译原理_P1004
龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...
最新文章
- 32岁前平凡无奇,鼓动同事创业,最终逆袭成硅谷首富
- [Cocoa]为已有的XCode工程创建Git仓库
- Keepalived高可用集群来实现web服务器负载均衡集群
- app和外部应用的关联及应用举例
- 基于AE的SimpleGIS框架的搭建
- 记一次因Redis使用不当导致应用卡死过程
- windows java路径问题_java中路径的问题
- ASP.NET2.0中数据源控件之异步数据访问
- HMM学习(2)-Generating Patterns
- thinkphp mysql 原生_第七节:thinkphp6数据库设计和原生查询
- ES6文档 思维导图笔记
- 使用函数式编程优化代码
- 零基础学 Python(17):if 条件语句
- 高通SDM439平台使能sensor hub的auto detect模式
- Linux终端收听mms流媒体电台
- java同花顺判定_笔试题:随机抽取五张牌 判断是否为同花顺
- 2020-05-11
- 使用calibre导出pdf格式时调整行间距
- 【工具】markdown
- FUEL: Fast UAV Exploration using Incremental Frontier Structure and Hierarchical Planning