一天早上遇到的事物,下午又恰好看到了专业的补充,对此将其记录下来。


二义性调用(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;
}

对于字面量整数来说,完全兼容 intlong 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 bT a, int b 的函数,来达成匹配。

然而对于整数字面量来说,一个默认行为就是,将其当作 int 进行处理,于是又回到了原点,int 都能无损转换为 long long,那谁来转换。显式标注并不能参与转换优先级竞争

只有当另一个未显式指定 int 类型的参数,其数值超过了 int 范围,那么才会将其定位至 long long, 从而达成匹配。


正常情况下,是很难遇到二义性调用的,想要随手写出这种函数都很难,知道这样一个术语,用于描述这种状况即可。

End

二义性调用(Ambiguous Call)相关推荐

  1. C++ 函数匹配 重载函数的调用规则

    学习<C++ Primer>一书中,函数匹配这一节内容信息较多,现截取重点内容记录于此.便于你对本文内容更好的理解,你需对类型提升.算术类型转换以及顶层cosnt,底层const有一定的了 ...

  2. 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...

  3. 深入理解C++重载函数

    深入理解C++重载函数 1.定义:C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数.类型或者顺序)必须不同,即函数的参数列表不同,也就是说用同一个运算符完成不 ...

  4. Scala入门到精通——第十八节 隐式转换与隐式参数(一)

    本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...

  5. 《C++ Primer 5th》笔记(6 / 19):函数

    文章目录 函数基础 局部对象 函数声明 分离式编译 参数传递 传递参数 传引用参数 使用引用避免拷贝 使用引用形参返回额外信息 const形参和实参 指针或引用形参与const 尽量使用常量引用 数组 ...

  6. ASP.NET文件夹

    ASP.NET文件夹 1. Bin文件夹 Bin文件夹包含应用程序所需的,用于控件.组件或者需要引用的任何其他代码的可部署程序集. 该目录中存在的任何.dll文件将自动地链接到应用程序.如果在该文件夹 ...

  7. 【java】理解和运用Java中的Lambda

    1.概述 转载:理解和运用Java中的Lambda 前提 回想一下,JDK8是2014年发布正式版的,到现在为(2020-02-08)止已经过去了5年多.JDK8引入的两个比较强大的新特性是Lambd ...

  8. [转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)...

    以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...

  9. 编译原理_P1001

    1 绝大部分软件使用高级程序设计语言来编写.用这些语言编写的软件必须经过编译器的编译,才能转换为可以在计算机上运行的机器代码.编译器所生成代码的正确性和质量会直接影响成千上万的软件.虽然大部分人不会参 ...

  10. 编译原理_P1004

    龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...

最新文章

  1. 32岁前平凡无奇,鼓动同事创业,最终逆袭成硅谷首富
  2. [Cocoa]为已有的XCode工程创建Git仓库
  3. Keepalived高可用集群来实现web服务器负载均衡集群
  4. app和外部应用的关联及应用举例
  5. 基于AE的SimpleGIS框架的搭建
  6. 记一次因Redis使用不当导致应用卡死过程
  7. windows java路径问题_java中路径的问题
  8. ASP.NET2.0中数据源控件之异步数据访问
  9. HMM学习(2)-Generating Patterns
  10. thinkphp mysql 原生_第七节:thinkphp6数据库设计和原生查询
  11. ES6文档 思维导图笔记
  12. 使用函数式编程优化代码
  13. 零基础学 Python(17):if 条件语句
  14. 高通SDM439平台使能sensor hub的auto detect模式
  15. Linux终端收听mms流媒体电台
  16. java同花顺判定_笔试题:随机抽取五张牌 判断是否为同花顺
  17. 2020-05-11
  18. 使用calibre导出pdf格式时调整行间距
  19. 【工具】markdown
  20. FUEL: Fast UAV Exploration using Incremental Frontier Structure and Hierarchical Planning

热门文章

  1. Unity官方实例教程 Space Shooter(太空射击游戏)
  2. 系统集成项目管理师和高级项目管理师考试心得
  3. FPGA实现AM调制
  4. Google Colab 挂载 Google Drive
  5. php 将图片裁剪成圆形图片,[PHP]把图片切成圆形
  6. 单层石墨烯结构图matlab,CST中如何建立单层石墨烯模型
  7. 【nvidia】1.命令行方式安装nvidia显卡驱动
  8. Unity里加速纹理压缩
  9. 计算机网络专业术语大全
  10. Java程序员面试分类真题(后附答案解析)