一个隐式类型转换引起的重载函数二义性错误
2011-11-11 15:57
288 查看
介绍因为隐式类型转换而引起的一个非常隐晦的错误
下述代码的目的是设计一个简单的类A,希望A的对象在标准输出和文件输出时的表现不同
代码段中有语句 fout << a.a,我们相当然以为这段代码实际会调用ostream& operator<<(ostream &, int)函数,这个失误导致了上述错误代码的编写
实际上这句代码还可以与ofstream& operator<<(ofstream& fout, const A& a)匹配,因为fout是ofstream类型对象,a.a是int类型对象但是却可以隐式转换为类型A的一个临时对象参与函数调用
选择最佳匹配函数的规则如下:
1.最佳匹配函数的每个实参的匹配都不劣于其它可行函数需要的匹配
2.最佳匹配函数至少有一个实参的匹配优于其他可行函数需要的匹配
基于上述规则,编译器无法在两个候选匹配函数中找出最佳匹配的那个,所以会导致编译出现二义性错误
解决方法:
我们的解决办法肯定是要控制int类型对象隐式转换为类型A的一个临时对象参与函数调用
办法一:将A的构造函数声明为explicit,防止在隐式转换的上下文中使用构造函数
办法二:将函数ofstream& operator<<(ofstream& fout, const A& a)声明改为ofstream& operator<<(ofstream& fout, A& a),防止这个函数的第二个参数由int隐式转换成A的临时对象
注:非const的引用参数只能是相同类型,加上const才能接受"右值(right value)"引用
总结:重载函数时要注意由隐式类型转换引起的非常难以辨识出来的二义性错误
下述代码的目的是设计一个简单的类A,希望A的对象在标准输出和文件输出时的表现不同
#include <iostream> #include <fstream> using namespace std; class A { public: int a, b; A(int n1 = 0, int n2 = 0): a(n1),b(n2) {} // 加上explicit,阻止隐式转换,则代码没问题; }; istream& operator>>(istream& in, A& a) { in >> a.a >> a.b; return in; } ostream& operator<<(ostream& out, const A& a) { out << a.a << " " << a.b << endl; return out; } ofstream& operator<<(ofstream& fout, const A& a) { fout << a.a << "xxx" << a.b << endl; // 如果注释掉这一句,则可以通过编译,说明问题出在这一句 return fout; } void main() { A a; cin >> a; cout << a; ofstream ff("output.txt"); ff << a; }乍一看,这段代码不会有什么问题,但实际上其中隐藏了一个错误,会导致不能通过编译,分析如下:
代码段中有语句 fout << a.a,我们相当然以为这段代码实际会调用ostream& operator<<(ostream &, int)函数,这个失误导致了上述错误代码的编写
实际上这句代码还可以与ofstream& operator<<(ofstream& fout, const A& a)匹配,因为fout是ofstream类型对象,a.a是int类型对象但是却可以隐式转换为类型A的一个临时对象参与函数调用
选择最佳匹配函数的规则如下:
1.最佳匹配函数的每个实参的匹配都不劣于其它可行函数需要的匹配
2.最佳匹配函数至少有一个实参的匹配优于其他可行函数需要的匹配
基于上述规则,编译器无法在两个候选匹配函数中找出最佳匹配的那个,所以会导致编译出现二义性错误
解决方法:
我们的解决办法肯定是要控制int类型对象隐式转换为类型A的一个临时对象参与函数调用
办法一:将A的构造函数声明为explicit,防止在隐式转换的上下文中使用构造函数
办法二:将函数ofstream& operator<<(ofstream& fout, const A& a)声明改为ofstream& operator<<(ofstream& fout, A& a),防止这个函数的第二个参数由int隐式转换成A的临时对象
注:非const的引用参数只能是相同类型,加上const才能接受"右值(right value)"引用
总结:重载函数时要注意由隐式类型转换引起的非常难以辨识出来的二义性错误
相关文章推荐
- 一个隐式类型转换引起的重载函数二义性错误
- 隐式类型转换导致重载函数二义性的问题
- 当心隐式类型转换导致重载函数产生二义性
- 隐式类型转换导致重载函数产生二义性
- 错误 2 无法将类型“int”隐式转换为“bool”
- 错误 与类型冲突 附注 的上一个隐式声明在此
- 更新数据库所有表的某一个指定字段 ,附加对‘将 varchar 值转换为数据类型为 int 的列时发生语法错误’处理方法
- SQL不是同一类型的变量赋值最好转换成统一类型,否则引起莫名错误
- 一个类型转换而引起的三级事件的一些思考
- 解决Html.CheckBoxFor中”无法将类型 bool 隐式转换为 bool。存在一个显式转换..."的方法
- 一个隐式转换引起的问题
- 提示错误(error C2665: “AfxMessageBox”: 2 个重载中没有一个可以转换所有参数类型)。
- 一个隐式转换引发的执行计划错误
- MVC 无法将类型“System.Collections.Generic.List<AnonymousType#1>”隐式转换为“System.Collections.Generic.IList<Mvc3Modeltest.Models.Movie>”。存在一个显式转换(是否缺少强制转换?))
- 无法将类型“string”隐式转换为“System.Data.SqlClient.SqlParameter”(错误)
- 一个VC编译错误引发的对显示类型转换的思考(static_cast、dynamic_cast和const_cast)
- explicit:C++规定,当定义了只有一个参数的构造函数时,同时也定义了一种隐式的类型转换
- VS编译错误:“到内置类型的函数样式转换只能接受一个参数”解决方案
- 在做一些复杂的类型转换之前(比如将一个数据转换成一个属性的类型,属性可能为可空类型)先判断该类型是否为可空类型,否则会报如下错误:
- 带有一个参数的构造函数的隐式类型转换和explicit 关键字