设计出上面两个式子正常运行才算合理的运行。
class Rational{ ... }; const Rational operator*(const Rational & lhs, const Rational & rhs) { return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator() * rhs.denominator() ); } Rational testOne(1, 4); Rational result; result = oneFourth *2; result = 2 * oneFourth; 通过 } |
按上面代码设计成非成员函数,那么在调用int类型整数的时候会发生隐式类型转换。
operaotr* 是否应该称为Rational class的一个友元函数呢?对本例子而言,完全没有必要。
如果你需要为某个函数所有参数进行类型转换,那么这个函数必须是个非成员函数。
4、谨慎使用隐式类型转换
我们对一些类型隐式转换无能为力,因为它们是语言本身的特性。不过当编写自定义类时,我们可以选择是否提供函数让编译器进行隐式类型转换。
有两种函数允许编译器进行隐式类型转换:单参数构造函数与隐式类型转换运算符。
public Name{ public: Name(const string& s); //转换string到Name ... }; class Rational { //有理数类 public: //转换从int到有理数类 Rational(int numerator=0,int denominatior =1); ... } |
C++是支持隐式类型转换的,例如在做运算的时候,或者传递参数给函数的时候常常会发生隐式类型转换。有两种函数允许编译器进行隐式转换。单参数构造函数和隐式类型转换运算符。
也许前面说道了一些隐式类型转换带来的方便之处,下面说说一些麻烦之处。
template<class T> class Array{ Array(int lowBound,int highBound); Array(int size); T& operator[](int index); ... }; bool oerpator==(const Array<int>& lhs,const Array<int>& rhs); Array<int> a(10); Array<int> b(10); ... for(int i=0;i < 10; ++i) if(a == b[i]) { ... } else { ... } |
如果这里不小心将数组a的下标忘记写了,这里编译器应该报出警告信息,但是其实是没有的。因为编译器将a看成Array<int>类型,b为 int,根据上面的经验,编译器看到一个non-explicit单参数构造函数其参数类型为int,而且operator需要一个Array<int>类型,那么编译器就这样做了,发生了隐式类型转换。相信如果真的发生这样,会很麻烦。
怎么样避免呢?将构造函数声明为explicit。避免隐式类型转换。