一,类型转换
class Fraction
{
public:
explicit Fraction(int num, int den=1)
: m_numerator(num), m_denominator(den)
{ cout << m_numerator << ' ' << m_denominator << endl; }
......
operator double() const {
return (double)m_numerator / m_denominator;
}
......
private:
int m_numerator; //
int m_denominator; //
};
转出去--利用转换函数(Conversion Function)
从一个类中转出去的方法是对int(),doube()等"操作符"进行重载.
值得注意的一点是,所有的转换函数都不需要声明返回参数类型,也不需要输入参数.可以通过(double) obj_of_Fraction 进行调用.
除了显式使用转换函数以外,转换函数也会进行隐式调用,例如:
Fraction f(3, 5);
double d = 4 + f;
在这种情况下,首先,编译器会检查是否存在+运算符的合适的函数重载.如果没有合适的函数重载被定义,则会先将f隐式转换为double,再进行相加.
转进来--合理使用explicit关键字避免二义性
构造函数可以实现"转进来"的目的.Fraction(4)可以创造一个分数,其分母为1,分子为4.
同样地,"转进来"的构造函数也可以被隐式调用.
例如对于语句 Fraction d2 = f + 4,第一步,编译器仍然会检查是否存在+运算符的合适的重载Fraction::operator +(double);如果没有合适的函数重载被定义,则会将4转换为分数,然后再进行相加.
不过,这种隐式转换有时反而是不利的,可能会导致二义性.考虑下面这种情况,如果在类的定义中存在下面的函数:
Fraction operator + (const Fraction & f) {
cout << "operator+(): " << f.m_numerator << ' ' << f.m_denominator << endl;
//... plus
return f;
}
那么,对于d2 = f + 4;有以下两种路径,产生了二义性从而不能通过.
f转double->double 相加->结果转回Fraction->赋值
4转Fraction->Fraction相加->赋值
为了消除这一二义性,在构造函数前面加了explicit关键字.Explicit关键字的意义是,这个函数只可以被显示调用,而不能被任何形式地隐式调用. (由于这种声明,Fraction a = 1也不能被调用了.)
如果给拷贝构造函数加explicit关键字,则Fraction B(A) 可以使用,Fraction B = A也不能使用了.
来源: