转换函数 及 explicit关键字
转换函数 VS non-explicit-one-argument构造函数
类的转换函数,是可以将该类类型转换为其他类型(自定义或内置)的一种重载函数。一般定义成 operator double() const; (可以将double换乘任意类型)。
注:const也可以不添加,添加是因为转换函数大多不会修改类成员变量,加上在实例化const类型时,依然可以调用该函数。
当类的构造函数只有一个argument(argument数量不同于参数列表中参数(parameter)的数量,可以理解为必须要传递的最少实参数)时,这种one argument构造函数,在合理的情况下会将第一个参数类型的变量转换成类类型。即可以将int型变量隐性的转换为Fraction类型。当在one argument构造函数前加上explicit关键字时(explicit关键字只对有一个参数的类构造函数有效),该构造函数就被定义为显式构造函数,可以防止类构造函数的隐式自动转换。
注:尽量将one argument构造函数定义为显示类型,以避免不合时宜的隐性转换。
class Fraction { public:
// explicit-one-argument构造函数
//explicit Fraction(int num, int den=1) // 显示构造函数 // non-explicit-one-argument构造函数 Fraction(int num, int den=1) // two parameters one argument函数 :m_numberator(num), m_denominator(den) { } operator double() const // 类型转换函数 { return (double)((double)m_numberator / m_denominator); } Fraction operator+(const Fraction& f) { return Fraction(this->m_numberator + f.m_numberator, this->m_denominator + f.m_denominator); } ~Fraction() {};
private: int m_numberator; int m_denominator; };
Fraction f(8, 5); double d = 4 + f; Fraction d = 4 + f; Fraction d = f + 4;
分析上述代码:
1. 在double d = 4 + f;中编译器在遇到全局操作符函数+时,发现有操作数为 Fraction类型,不是+函数的输入参数类型,进而去寻找是否有可以将Fraction类转换成int或double的类型转换函数。找到Fraction定义了double,则调用。
2. 在Fraction d = 4 + f;中4+f的操作编译器的处理和1相同,在完成+计算得到double类型数据后,又调用隐式构造函数Fraction(int num, int den=1)。若在构造函数前边加上explicit关键字(如注释部分),则变成显示构造函数(explicit-one-argument构造函数),此时在调用Fraction d = 4 + f;则会出错: “初始化”: 无法从“double”转换为“Fraction” 。
3. 在Fraction d = f + 4;中会出错:“Fraction::operator +”: 2 个重载有相似的转换。出错原因:在遇到操作符+时,a. 可以调用Fraction的操作符重载函数Fraction operator+(const Fraction& f),则需要将4通过隐式构造转换成Fraction类型,再做+操作;b.也可以将+看作全局操作符,此时又可以将f转换成double,进行+操作。因为a,b两种都可行,所以编译器无法自动选择哪种方式运行,故报错。此时将Fraction类中的double或者+重载函数去掉,再编译是可以通过的,即切断一种可以编译的途径,使其不能按照该方式编译。
参考:
侯捷的c++课程
浙公网安备 33010602011771号