15.10 选择一个转换
用户定义的转换包括调用转换函数,或者调用构造函数
class Number{ public : operator float(); operator int(); //... }; Num num; float ff = num //调用operator float()函数。
因为:
operator float() ->精确匹配
operator int() ->标准转换
精确匹配优于标准转换
两个构造函数都能把一个值变成转换的目标类型,如:
class SmallInt{ public : SmallInt(int val):val(val){} SmallInt(double dval) :value(static_cast<int> (dval)){} //... } extern vodi manip(const SmallInt &); int main(){ double dobj; manip(dobj); //这里调用SamllInt(double) }
SmallInt(double)属于精确匹配
SmallInt(int) 属于标准匹配
当执行一完成一个用户定义转换序列后,再执行一个标准准换,
有可能出现问题,如:
class Number{ public: operator float(); operator int(); //... } Number num; long lval =num; //错误,二义性
operator float() ->标准转换
operator int()->标砖转换
两种转换是一样的,编译器无法选择出更优的选择,不过可以指定强转换来指定,如:
long lval = static_cast<int>(num);将调用Number::operator int()转换函数
在为隐式转换选择一个用户定义的转换序列时,如果这两个类定
义了互相转换的函数,可能出现二义性,如:
class SmallInt{ public: SmallInt(const Number&); //... } class Number{ public: operator SamllInt(); //... } extern void compute(SmallInt); extern void Number num; compte(num); //错误,两个可能的转换
num转换成SmallInt对象,可以通过构造函数来转换,也可以通过
转换函数来转换,这两种方式都属于用户定义的转换,优先级别
是一样的。
可以通过显示调用来解决,如:
compute(num.operator SmallInt());//显示调用解决二义性问题
15.10.2候选函数
当函数调用的实参是类类型,指向类类型的指针或者是指向成员
的指针,需要为该调用考虑一个很大的函数集,作为候选函数。
Namespace NS{ class SmallInt{ friend SmallInt add(SmallInt,int){//...} }; class String{//...}; String add(const String &,const String &); } const matrix& add(const matrix &,int); double add(double,double); int main(){ NS::SmallInt si(15); add(si,566); //调用友元函数 return 0; }
候选函数:
1.全局函数
add(const matrix &,int)
add(double,double)
2.名字空间函数
NS::add(const String &,const String &)
3.友元函数
NS::add(SmallInt ,int)
重载函数选择友元函数作为最佳匹配函数,因为友元函数的两个
实参是精确匹配
15.10.3 类域中的函数所调用的候选函数
namespace NS{ struct myClass{ void k(int); static void k(char*); void mf(); }; int k(double); }; void h(char); void NS::myClass::mf(){ h('a'); //调用全局h(char) k(4); //调用myClass::k(int) }
函数调用在查找过程中,一旦找到了函数声明,则查找在调用点
可以见的候选函数,找到,则退出查找过程。
15.10.4对用户定义的转换序列化分等级
class SmallInt{ public SmallInt(int); }; extern void calc(double); extern void calc(SmallInt); int ival; int main(){ calc(ival); //调用calc(double); }
当用户定义的转换与标准转换都可行时,优先考虑标准转换。
如果两个转换都是用户定义的转换,则无法判断优先级,程序出现二义性,如:
class Number{ public: operator SmallInt(); operator int(); }; extern void calc(int); extern void calc(SmallInt); extern Number num; clac(num); //错误,二义性
Number对象定了两个转换函数,这两个转换函数具有相同的优先级。可以显示指定来解决二义性,如
calc(static_cast<int>(num)); //调用int()转换函数
calc(static_cast<SmallInt>(num)); //调用SmallInt()转换函数
如果Number中没有Int(),调用calc(num)还是二义的吗?
也是二义的,虽然SmallInt可以再次转换的Int型,但是在转换过程中,只能存在一个用户定义的转换,如果Number对象先转换成SmallInt对象,SmallInt对象再转换成Int对象,存在两次用户定义的转换。