考虑非静态成员函数的运算符==重载

4
我定义了一个类,就像这样
using namespace std;
class foo {
public:
  typedef std::pair< int, int > index;
  bool operator == ( const index &l, const index &r )
  {
    return (l.first == r.first && l.second == r.second);
  }
  void bar()
  {
    index i1;
    i1.first = 10;
    i1.second = 20;
    index i2;
    i2.first = 10;
    i2.second = 200;
    if (i1 == i2)
       cout << "equal\n";
  }
};

然而,我在Windows系统中遇到了这个错误。
error C2804: binary 'operator ==' has too many parameters

在Linux中出现的这个错误。
operator==(const  std::pair<int, int>&, const std::pair<int, int>&)’ must take exactly one argument

我发现了这个主题“重载运算符== complaining of 'must take exactly one argument'”,似乎是与类中的静态和非静态函数有关的问题。然而我不知道如何应用this
例如,以下内容是不正确的。
  bool operator == ( const index &r )
  {
    return (this->first == r.first && this->second == r.second);
  }

我该如何解决这个问题?

1
std::pair没有已经有==运算符了吗? - Alex Chamberlain
4个回答

5
operator==(const std::pair& lhs, const std::pair& rhs);

The operator==可以通过以下两种方式实现:

  • 作为成员函数:在这种情况下,该函数接受一个参数,并在左操作数上调用,该左操作数隐式地作为this指针传递给函数。
  • 作为非成员函数:在这种情况下,该函数接受两个参数,即左右操作数。

由于您正在为std::pair实现operator==,因此无法将其实现为成员函数(of std::pair)。您能选择的选项是非成员函数。

因此,将它实现为类外部如下:

operator==(const std::pair& lhs, const std::pair& rhs);
bool operator==(std::pair<int,int> const & l, std::pair<int,int> const & r)
{
    return (l.first == r.first && l.second == r.second);
}

但是,除非你想以不同的方式实现它,否则你并不需要自己实现它。 标准库已经为 std::pair 提供了一个通用版本operator==,它对比配对中的值的字典序,就像我上面所做的那样,即将第一个元素和第一个元素进行比较,并将第二个元素和第二个元素进行比较。如果您需要以不同的方式进行比较,那么只有提供自己特定的定义(非模板版本)才可以。

当您需要为您定义的类型添加 operator== 时,上述提到的要点是值得注意的。


2
请不要这样做。std::pair已经有了一个通用的operator==重载,它会执行明智的操作(将第一个与第一个进行比较,将第二个与第二个进行比较)。只需创建自己的结构体来保存两个整数,而不是作为std::pair<int,int>的typedef。 - Benjamin Lindley
@BenjaminLindley:是的,我写了那个。 - Nawaz
@Nawaz:我的评论是针对OP的。请注意,标准库版本不适用于他的情况,因为他将lhs.first与rhs.second进行比较,并完全忽略了rhs.first。这就是为什么我建议创建自己的结构体。除非那是一个打字错误。 - Benjamin Lindley
1
不好意思,那是个打错字。应该是“first”而不是“second”。感谢您的评论。 - mahmood
@BenjaminLindley:我注意到了,我认为那是一个打字错误。 - Nawaz

3
你需要将operator==移出foo类:
bool operator == ( const foo::index &l, const foo::index &r )
{
  return (l.first == r.second && l.second == r.second);
}

class foo {
public:
   typedef std::pair< int, int > index;
  void bar()
  {
    index i1;
    i1.first = 10;
    i1.second = 20;
    index i2;
    i2.first = 10;
    i2.second = 200;
    if (i1 == i2)
       cout << "equal\n";
  }
};

此外,注意到 std::pair 已经有了重载的 operator==,请参考: 链接,如果必要,您可以重新考虑是否需要再次编写自己的代码。

显然,您正在更改索引的名称。为什么不将typedef保留在原处,并在函数中限定名称呢? - Alex Chamberlain

2

如果在一个类中重载==运算符,应该只接受一个参数,这样才能在当前对象和参数之间进行比较。


那么 return 语句长什么样子? - mahmood

2
你可以将该运算符移出类,这样你就可以使用两个操作数。事实上,在这种情况下,保留它在类中是没有意义的,因为你只是比较成员变量而不是类本身。
的确,如果pair已经定义了你写的运算符,我不会感到惊讶。
编辑:是的,看起来pair已经实现了这个 两个pair对象相等,当且仅当两个对象的第一个元素相等,并且两个对象的第二个元素也相等——它们都必须匹配。
附言:我想你的意思是
return (l.first == r.first && l.second == r.second);
                    ^^^^^^

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接