C++布尔运算符==

5
我刚刚试着写了一个比较两个对象的函数,但是报错如下:
错误:bool Duree::operator==(const Duree&, const Duree&)函数必须只有一个参数。
我该怎么解决?谢谢。
Duree.h
#ifndef DEF_DUREE
#define DEF_DUREE

class Duree
{
public:
    Duree(int heures = 0, int minutes = 0, int secondes = 0);
    bool estEgal(Duree const& b) const;
    bool operator==(Duree const& a, Duree const& b);

private:
    int m_heures;
    int m_minutes;
    int m_secondes;
};

#endif

Duree.cpp

#include "Duree.h"

Duree::Duree(int heures, int minutes, int secondes) : m_heures(heures), m_minutes(minutes), m_secondes(secondes)
{

}

bool Duree::estEgal(Duree const& b) const
{
    return (m_heures == b.m_heures && m_minutes == b.m_minutes && m_secondes == b.m_secondes);
}

bool operator==(Duree const& a, Duree const& b)
{
    return a.estEgal(b);
}

Main.cpp

#include <iostream>
#include "Duree.h"
using namespace std;

int main()
{
    Duree fisrt(10, 10, 10), second(15, 20);

    if (fisrt == second)
        cout << "Les durees sont identiques";
    else
        cout << "Les durees sont differentes";
    return 0;
}

可能是运算符重载的重复问题。 - Deduplicator
4个回答

9

你可以将operator==声明为具有两个参数的自由函数:

bool operator==(Duree const& a, Duree const& b);

或者作为一个只有一个参数的成员函数:

bool Duree::operator==(Duree const& b);

这是因为当你执行x == y时,你只比较了两个对象。如果你有一个成员函数,那么会传递一个隐含的“this对象”(你在其上调用operator==),使其成为3个参数而不是2个。
话虽如此,从你编写代码的方式来看,我猜你只是忘记在类定义中在operator==声明前加上friend了。
可能有用的提示:你可以在支持它的编译器上(基本上每个“主要”编译器)使用#pragma once代替包含保护。 :)

3
更倾向于使用自由函数,因为它对操作数具有对称性,而成员函数则没有。 - Jens

2
将您的原型更改为bool operator==(Duree const& rhs);,或将其作为类Duree之外的自由函数。


1
始终优先使用非成员(自由)二元函数。否则,如果您使用不同类型重载运算符,则可能会遇到问题。考虑以下人为代码:
struct Foo {
   int x;
   bool operator==(Foo const & other) const { return x == other.x; }
};

这对比较两个Foo对象来说很好用。但是它存在一个问题。假设你还想将其与int进行比较:
struct Foo {
   int x;
   bool operator==(Foo const & other) const { return x == other.x; }
   bool operator==(int other) const { return x == other; }
};

现在你可以进行单向比较,但不能进行双向比较:

Foo a, b;
...
a == b; // ok
a == 123; // ok
123 == a; // ERROR

作为成员函数,对象必须在右侧。 简单来说,将int-Foo重载移出类,并创建两个版本,Foo==int和int==Foo?(注意,将它们声明为类内友元也可以实现,但我这里不展示。)
struct Foo {
   int x;
   bool operator==(Foo const & other) const { return x == other.x; }
};

bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }

现在一切都正常了,对吧?我们有一些成员和非成员操作符的混合。

a == b; // ok
a == 123; // ok
123 == a; // ok

直到Foo开始使用运算符的成员函数...

struct Foo {
   int x;
   bool operator==(Foo const & other) const { return x == other.x; }

   void g(int x);
};

bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }

void Foo::g(int x)
{
    Foo f = getOtherFoo();
    if (f == x) { // ERROR!  cannot find operator==(Foo,int)
      //...
    }
}

它仍然存在问题!在Foo的内部成员中,它无法看到非成员运算符,因为成员运算符将其隐藏!g()将无法编译,因为它无法将Foo与int进行比较。将所有运算符移出将解决此问题,因为然后所有重载都在同一作用域中。(请记住,名称查找会继续搜索外部作用域,直到找到正在查找的名称的第一个情况,然后仅考虑在该作用域中找到的所有名称。在g()中,它的作用域位于类中,并且由于它在类内找到了一个版本的运算符(错误的版本),因此它永远不会在类外寻找更多的重载。但如果它们全部在类外,它将同时找到它们。)
struct Foo {
   int x;
   void g(int x);
};

// NON MEMBER
bool operator==(Foo const & lhs, Foo const & rhs) { return lhsx == rhs.x; }
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }

void Foo::g(int x)
{
    Foo f = getOtherFoo();
    if (f == x) { // OK now, finds proper overload
      //...
    }
}

现在,它可以在所有情况下编译。这就是为什么他们说,“始终优先考虑制作非成员二元运算符重载”。否则,您可能会遇到对称性和隐藏问题。

-3
我也遇到了同样的问题。 在 main() 之前将带有两个参数的 operator== 放回 main.cpp 中即可解决 ;)

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