《C++ Primer Plus》11. 使用类
运算符重载
可重载的运算符:
| 类型 | 运算符 |
|---|---|
| 双目算术运算符 | +、-、*、/、% |
| 关系运算符 | ||、&&、! |
| 单目运算符 | +(正)、-(负)、*(解引用)、&(取地址) |
| 位运算符 | |、&、~、^、<<、>> |
| 赋值运算符 | =、+=、*=、/=、%=、&=、|=、^=、<<=、>>= |
| 空间申请与释放 | new、delete、new[]、delete[] |
| 其他运算符 | ()(函数调用)、->(成员访问)、,(逗号)、[](下标) |
不可重载的运算符:
.:成员访问运算符.*、->*:成员指针访问运算符:::域运算符sizeof:长度运算符?::三目条件运算符#:预处理符号
运算符重载有两种形式:成员函数重载和非成员函数重载(友元),其中有一部分运算符只能通过成员函数进行重载:
=:赋值运算符():函数调用运算符[]:下标运算符->:通过指针访问类成员的运算符
在重载运算符时,只能选择其中一种形式,而不能同时选择
运算符重载必须至少有一个操作数是用户定义的类型(不需要都是),返回值可以任意,但必须满足 C++ 的类型系统约束
友元
有三种:友元函数、友元类、友元成员函数
需要友元的一个场景是不同类型之间的运算符重载,例如 A = 3 * B,我们必须构造一个函数 T operator*(int x, const T & y)
将函数放到类的声明中,并且加上 friend 就能声明一个友元函数:
friend T operator*(int x, const T & y);
- 虽然这个函数在类声明中声明,但是它不是成员函数,因此不能使用成员运算符(
.operator*)调用 - 虽然它不是成员函数,但是它与成员函数的访问权限相同
实现这个友元函数时,无需限定类作用域(不需要 T::)
类的自动转换和强制类型转换
- 从其他类型转换到当前类:使用单参数构造函数
- 从当前类转换到其他类型:使用转换函数
operator int();、operator double();、operator T2();等
如果在构造函数前或者转换函数前添加 explicit,那么就只能显式转换,否则可以隐式转换
注意转换函数没有返回类型和参数,但必须返回值
经验表明,最好不要依赖这种隐式转换