14.9 重载、类型转换与运算符
在7.5.4节中,我们看到由一个实参调用的非显式构造函数定义了一种隐式的类型转换,这种构造函数将实参类型的对象转换成类类型。
我们同样能定义对于类类型的类型转换,通过定义类型转换运算符可以做到这一点。转换构造函数和类型转换运算符共同定义了类类型转换(class-type conversions), 这样的转换也被称作用户自定义的类型转换(user-defined conversions)。
- 类型转换运算符
- 类型转换运算符(conversion operator)是类的一种特殊成员函数,它负责将一个类类型的值转换成其他类型。一般形式:operator type() const; 其中type表示某种类型。
- 我们不允许转换成数组或函数类型,但允许转换成指针(包括数组指针及函数指针)或引用类型。
- 类型转换运算符既没有显示的返回类型,也没有形参,而且必须定义成类的成员函数。类型转换运算符通常不应该改变待转换对象的内容,因此,类型转换运算符一般被定义成const成员。
NOTE:一个类型转换函数必须是类的成员函数;它不能声明返回类型,形参列表也必须为空。类型转换函数通常应该是const。
- 定义含有类型转换符的类
1 2 3 4 5 6 7 8 9 10 11 |
class SmallInt { public: SmallInt(int i = 0): val(i) { if (i < 0 || i > 255) throw std::out_of_range("Bad SmallInt value"); } operator int() const { return val; } private: std::size_t val; }; |
SmallInt类既定义了向类类型的转换,也定义了从类类型向其他类型的转换。其中构造函数将算符类型的值转换成SmallInt对象,而类型转换运算符将SmallInt对象转换成int:
1 2 3 |
SmallInt si; si = 4; //首先将4隐式地转换成SmallInt,然后调用SmallInt::operator= si + 3; //首先将si隐式地转换成int,然后执行整数的加法 |
- 显示的类型转换运算符
C++11新标准引入了显示的类型转换运算符(explicit conversion operator):
1 2 3 4 5 6 |
class SmallInt { public: //编译器不会自动执行这一类型转换 explicit operator int() const { return val; } //其他成员与之前的版本一致 }; |
和显示的构造函数一样,编译器(通常)也不会将一个显式的类型转换运算符用于隐式类型转换:
1 2 3 |
SmallInt si = 3; //正确:SmallInt的构造函数不是显式的 si + 3; //错误:此处需要隐式的类型转换,但类的运算符是显式的 static_cast<int>(si) + 3; //正确:显式地请求类型转换 |
该规定存在一个例外,即如果表达式被用作条件,则编译器会将显式地类型转换自动应用于它。换句话说,当表达式出现在下列位置时,显示的类型转换将被隐式地执行:(1)if、while及do语句的条件部分;(2)for语句头的条件表达式;(3)逻辑非运算符(!)、逻辑或(||)、逻辑与(&&)的运算对象;(4)条件表达式(? :)的条件表达式。
- 避免有二义性的类型转换
- 如果类中包含一个或多个类型转换,则必须确保在类类型和目标类型之间只存在唯一一种转换方式。否则的话,我们编写的代码将很可能会具有二义性。
WARNING:通常情况下,不要为类定义相同的类型转换,也不要在类中定义两个及两个以上转换源或转换目标是算术类型的转换。
ps.这部分内容看的有点乏味,笔记内容较少。