《C++ Primer Plus》11. 使用类

运算符重载

可重载的运算符:

类型运算符
双目算术运算符+-*/%
关系运算符||&&!
单目运算符+(正)、-(负)、*(解引用)、&(取地址)
位运算符|&~^<<>>
赋值运算符=+=*=/=%=&=|=^=<<=>>=
空间申请与释放newdeletenew[]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,那么就只能显式转换,否则可以隐式转换

注意转换函数没有返回类型和参数,但必须返回值

经验表明,最好不要依赖这种隐式转换