Skip to content

ch13 operator overloading

这部分讲运算符重载。

成员函数与非成员函数

运算符重载能够通过成员函数与非成员函数,两者的区别如下:

  • 成员函数天生能够访问类内部的所有属性,而非成员函数需要是友元才能访问内部的所有属性表。
  • 成员函数只能将类对象作为左操作数,非成员函数可以将类对象成为左操作数或者右操作数。
  • 非成员函数能够实现左操作数的隐式转换。

很多运算符只能作为成员函数实现,如 =(拷贝运算符)、[](下标访问运算符)、()(函数调用运算符,实现这个函数,对象能和函数一样调用)、T(向类型 T 转换的运算符)。

在类中,一般不重载 &&||,重载这两个运算符会导致逻辑判断的时候短路失效。在 cpp 20 中可以对于比较形的运算符可以只实现 <=>==,其他能够由编译器自动生成。如果 <=>== 没有重载,编译器也会自动生成,但是要求内部的每个成员变量都是能够使用 <=>== 比较的,比较的顺序为成员变量定义的顺序,如果内部的成员变量也有 <=>== 没有实现,就会自动将这个类的 <=>== 打上 delete 标记,表示不能使用。

重载类型转换

对于类型转换的重载主要是为了可以让自定义的类型表现的更像内置的类型。主要的使用场景如下:

  1. 进行类型转换 static_cast<> 的时候会调用这个函数。
  2. 在进行计算的时候将对象向特定类型的转化。
  3. 能够加强和第三方库的合作,通过重载将自定义类型转换为第三方库所需的类型来实现合作。
  4. 可能影响到函数重载的决策。

重载赋值运算符

赋值运算符也可以成为拷贝运算符,和拷贝构造函数很像,但是拷贝构造运算符永远作用在已经创建出的对象上,class A = B 这里调用的不是拷贝构造运算符,因为对象还没被创建,这里调用的是拷贝构造函数。如果没有重载拷贝运算符,编译器会自动生成。

在重载拷贝运算符的时候需要检查传入的对象,避免自己等于自己这样的拷贝情况的发生。同时拷贝运算符永远返回对于对象的引用,即返回 *this