隐式类型转换的形式为operator 关键字,其后紧跟一个类型符号。不需要定义函数的返回类型,因为这个函数的名字就是返回类型。 - 好处:可以很方便的满足我们隐式类型转换的要求:
class Rational{ public: ... operator double() const;//转换Ratioanl类成double类型 }; Rational r(1,2); double d=0.5*r;//转换r到double,然后做乘法运算 坏处:可以很方便地让我们进入一个坑中而不自知: //假设,我们此时没有定义关于Rational的operator<<重载运算 Rational r(1,2); cout<<r;本来针对这种操作,我们的结果应该为ERROR的,但是此时程序呢?运行正常,结果打印出0.5,哈哈,这时候我们发现原来是隐式类型转换函数在这儿捣乱,此时它们的存在将导致错误! 这种问题如何结局呢?我们通常用不使用语法关键字的等同的函数来提点隐式类型转换重载运算符,例如:
class Rational{ public: ... double asDouble() const; }; //此时,假设我们仍旧没有定义operator<<运算符 Rational r(1,2); cout<<r;//ERROR,Ratioanl对象没有operator<< cout<<r.asDouble();我们原本计划比较a[i]和b[i],然而忘了写参数而导致Array<int>和一个int型进行比较,很尴尬吧!会出错吗?答案是否定的,因为存在单参数构造函数,编译器会自动将后面的b[i]隐式类型转化为Array<int>类型,等价与两个Array<int>类型的数据进行比较,然而逻辑上却又很大错误。 解决办法有两个: 1)简单的方式就是利用编译器的特性、explicit关键字,为了解决隐式类型转化而特别引入的这种特性。针对上面有问题的代码我们可以按照如下方式进行解决:
template <class T> class Array{ public: ... explicit Array(int size); ... }; Array<int> a(10); Array<int> b(10); if(a==b[i])...//ERROR,没法进行隐式类型转换 if(a==Array<int>(b[i])) ...//OK,逻辑上有问题 if(a==static_cast<Array<int> >(b[i])) ...//OK,逻辑上有问题 if(a==(Array<int>)b[i]) ...//Ok,C分割转换,逻辑上有问题2)声明一个内部类,每次转换的时候需要先转换为内部类,然后才能进行转换,避免直接隐式类型转换:
template <class T> class Array{ public: class ArraySize{ public: ArraySize(int numELements):theSize(numElements){} int size() const {return theSize;} private: int theSize; }; Array(int lowBound,int highBound); Array(ArraySize size); ... };注意ArraySize总是和Array一起使用,因此,我们必须将ArraySize声明为公有,让任何人都可以使用它。