有关C++中类类型转换操作符总结(必看篇)
实例如下:
classSmallInt{ public: SmallInt(inti=0):val(i) { if(i<0||i>255) throwstd::out_of_range("BadSmallIntinitializer"); } operatorint()const{returnval;} private: std::size_tval; };
转换函数采用如下通用形式:
operatortype();
type表示内置类型名、类类型名或由类型别名定义的名字。对任何可作为函数返回类型的类型(除了void之外)都可以定义转换函数。一般而言,不允许转换为数组或函数类型,转换为指针类型(数据和函数指针)以及引用类型是可以的。转换函数必须是成员函数,不能指定返回类型,并且形参表必须为空。operatorint返回一个int值;如果定义operatorSales_item,它将返回一个Sales_item对象,诸如此类。转换函数一般不应该改变被转换的对象。因此,转换操作符通常应定义为const成员。
SmallIntsi;
doubledval;
si>=dval//siconvertedtointandthenconverttodouble
优点:类类型转换可能是实现和使用类的一个好处。通过为SmallInt定义到int的转换,能够更容易实现和使用SmallInt类。int转换使SmallInt的用户能够对SmallInt对象使用所有算术和关系操作符,而且,用户可以安全编写将SmallInt和其他算术类型混合使用的表达式。定义一个转换操作符就能代替定义48个(或更多)重载操作符,类实现者的工作就简单多了。
缺点:二义性
classSmallInt{ public: SmallInt(int=0); SmallInt(double); //Usuallyitisunwisetodefineconversionstomultiplearithmetictypes operatorint()const{returnval;} operatordouble()const{returnval;} private: std::size_tval; }; voidcompute(int); voidfp_compute(double); voidextended_compute(longdouble); SmallIntsi; compute(si);//SmallInt::operatorint()const fp_compute(si);//SmallInt::operatordouble()const extended_compute(si);//error:ambiguous
对extended_compute的调用有二义性。可以使用任一转换函数,但每个都必须跟上一个标准转换来获得longdouble,因此,没有一个转换比其他的更好,调用具有二义性。
如果两个转换操作符都可用在一个调用中,而且在转换函数之后存在标准转换,则根据该标准转换的类别选择最佳匹配。若无最佳匹配,就会出现二义性。
再比如:
可能存在两个转换操作符,也可能存在两个构造函数可以用来将一个值转换为目标类型。
考虑manip函数,它接受一个SmallInt类型的实参:
voidmanip(constSmallInt&); doubled;inti;longl; manip(d);//ok:useSmallInt(double)toconverttheargument manip(i);//ok:useSmallInt(int)toconverttheargument manip(l);//error:ambiguous
第三个调用具有二义性。没有构造函数完全匹配于long。使用每一个构造函
数之前都需要对实参进行转换:
1.标准转换(从long到double)后跟SmallInt(double)。
2.标准转换(从long到int)后跟SmallInt(int)。
这些转换序列是不能区别的,所以该调用具有二义性。
当两个类定义了相互转换时,很可能存在二义性:
classIntegral; classSmallInt{ public: SmallInt(Integral);//convertfromIntegraltoSmallInt }; classIntegral{ public: operatorSmallInt()const;//convertfromIntegraltoSmallInt }; voidcompute(SmallInt); Integralint_val; compute(int_val);//error:ambiguous
实参int_val可以用两种不同方式转换为SmallInt对象,编译器可以使
用接受Integral对象的构造函数,也可以使用将Integral对象转换为
SmallInt对象的Integral转换操作。因为这两个函数没有高下之分,所以这
个调用会出错。
在这种情况下,不能用显式类型转换来解决二义性——显式类型转换本身既可以使用转换操作又可以使用构造函数,相反,需要显式调用转换操作符或构造函数:
compute(int_val.operatorSmallInt());//ok:useconversionoperator compute(SmallInt(int_val));//ok:useSmallIntconstructor
改变构造函数以接受constIntegral引用:
classSmallInt{ public: SmallInt(constIntegral&); };
则对compute(int_val)的调用不再有二义性!原因在于使用SmallInt构造函数需要将一个引用绑定到int_val,而使用Integral类的转换操作符可以避免这个额外的步骤。这一小小区别足以使我们倾向于使用转换操作符。
显式强制转换消除二义性
classSmallInt{ public: //Usuallyitisunwisetodefineconversionstomultiple arithmetictypes operatorint()const{returnval;} operatordouble()const{returnval;} //... private: std::size_tval; }; voidcompute(int); voidcompute(double); voidcompute(longdouble); SmallIntsi; compute(si);//error:ambiguous
可以利用显式强制转换来消除二义性:
compute(static_cast<int>(si));//ok:convertandcallcompute(int)
显式构造函数调用消除二义性
classSmallInt{ public: SmallInt(int=0); }; classIntegral{ public: Integral(int=0); }; voidmanip(constIntegral&); voidmanip(constSmallInt&); manip(10);//error:ambiguous
可以用显示构造函数消除二义性:
manip(SmallInt(10));//ok:callmanip(SmallInt) manip(Integral(10));//ok:callmanip(Integral)
标准转换优于类类型转换
classLongDouble { public: LongDouble(double); //… }; voidcalc(int); voidcalc(LongDouble); doubledval; calc(dval);//whichfunction
最佳可行函数是voidcalc(int),调用此函数的转换为:将实参double类型转换为int类型的,为标准转换;调用voidcalc(LongDouble)函数时,将实参从double转换为LongDouble类型,为类类型转换,因为标准转换优于类类型转换,所以第一个函数为最佳可行函数。
以上这篇有关C++中类类型转换操作符总结(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。