HOWTO · C++

如何在 C++ 中重载 == 运算符

这是一个在 C++ 中实现 == 运算符重载的编程教程。

本页内容

类可以通过实现 operator== 来定义相等性。该函数应比较代表对象值的字段。下面的 Employee 示例比较了姓名和薪资,然后展示了 == 如何报告相符和不同的员工。

C++ 中的运算符重载

运算符重载为用户自定义类型(例如类或结构)赋予现有运算符含义。成员重载通常具有以下形式:return_type operator symbol(parameters)。例如,operator== 是用于重载相等性的函数名称。

重载必须至少涉及一个用户自定义类型;它不能重新定义其操作数全是内置类型(例如 int 或 char)的运算。它也不能更改运算符的优先级、操作数数量或结合性。语法和熟悉的表达式保持不变,因此调用者可以写 first == second,而不是直接调用比较方法。

有些运算符无法重载,包括 ::、.、.*、?: 和 sizeof。typeid 运算符也无法重载。

在 C++ 中重载 == 运算符

对于类,在编写函数之前,请先决定哪些字段定义了相等性。这个 Employee 值同时使用 name 和 salary;如果其中任何一个不同,对象就会被比较为不相等。const 成员函数和 const 引用参数允许在不复制或修改任一对象的情况下进行比较。

#include <iostream>
#include <string>

class Employee {
 public:
  Employee(std::string name, int salary)
      : name_(name), salary_(salary) {}

  bool operator==(const Employee& other) const {
    return name_ == other.name_ && salary_ == other.salary_;
  }

 private:
  std::string name_;
  int salary_;
};

int main() {
  const Employee first("David", 1000);
  const Employee same("David", 1000);
  const Employee different_salary("David", 1200);

  std::cout << (first == same ? "Equal" : "Not equal") << '\n';
  std::cout << (first == different_salary ? "Equal" : "Not equal") << '\n';
}
Equal
Not equal

当所选的两个字段都相符时,输出显示 Equal;当薪资不同时,显示 Not equal。如果该类日后增加了另一个值字段,请在该字段应影响相等性时将它纳入。

在类层次结构中重载 == 运算符

基类的相等性函数仅检查其实现中包含的基类状态。它可以通过继承的成员对派生对象调用,但不会自动检查派生类添加的成员。派生类型不必定义相等性,除非其自身的比较语义需要包含额外的状态。

例如,如果 A 存储了 foo 并定义了 bool operator==(const A& other) const,那么该函数会比较 foo。如果 B : public A 增加了 bar,请在 B 的相等性应包含 bar 时定义 B 的比较:其结果可以将 A::operator==(static_cast<const A&>(other)) 与 bar == other.bar 结合。这会明确地比较基底部分和派生字段。当派生重载具有相同名称时,它可能会在普通查找期间隐藏基类重载;如果两个比较都应该可用,请使用刻意的重载集合。

表达式的静态操作数类型决定了哪些重载会参与。对于多态基类引用,基类比较仍然比较的是基类视图;它不会动态地发现并比较派生成员。因此,跨多态层次结构的相等性需要一个明确的策略,说明不同的动态类型是否可以比较为相等,并且在两种操作数顺序下行为一致。请保持规则一致,以便相等性保持对称,并反映您的类型承诺代表的值。