user3521310
user3521310

Reputation:

C++ Bool Operator==

I just tried to make a function that compares 2 objects, but it gives me:

Error: bool Duree::operator==(const Duree&, const Duree&) must take exactly one argument

How can I solve this? Thank you.

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;
}

Upvotes: 5

Views: 14331

Answers (4)

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

Always prefer the binary functions to be NON MEMBER (free) functions. Otherwise you can run into problems if you overload the operator with different types. Consider the following contrived code:

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

This should work fine for comparing two Foos together. But it has a problem. Suppose you also want to compare to an int:

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

Now you can compare one way but not the other:

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

As member function the object must be on the right hand side.

Simple, move the int-Foo overloads out of the class, and make two versions, Foo==int and int==Foo? (Note, making them friends declared inside the class can accomplish that too, FWIW, but I'm not showing it here.)

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; }

So now everything works, right? We have a mix of member and non-member operators.

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

Until Foo starts getting member functions that want to use the operators...

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)
      //...
    }
}

It STILL has a problem! Inside members of of Foo, it cannot see the non-member operators because the member one hides them! g() will not compile since it can't compare Foo to int. Moving all of the operators out will resolve it, since then all of the overloads are in the same scope.

(Remember, name-lookup keeps searching outer scopes UNTIL it finds the fist case of the name it is looking for, and then only considers all the names it finds in that scope. Inside g(), it's scope is in the class, and since it finds one version of the operator inside the class (the wrong one), it never looks outside the class for more overloads. But if they are all outside the class, it'll find them all at the same time.)

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
      //...
    }
}

Now, it compiles in all the cases. That's why they say, "Always prefer to make non-member binary operator overloads." Otherwise you can end up with symmetry and hiding problems.

Upvotes: 1

Nym&#39;
Nym&#39;

Reputation: 1

I'm on the same kind of issue. Worked by putting operator== with two arguments back in main.cpp before the main() ;)

Upvotes: -3

Shoe
Shoe

Reputation: 76298

Either you declare operator== as a free function with two arguments:

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

or as a member function with only one argument:

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

This is because when you do x == y you are comparing only two objects. If you have a member function there's an implicit "this object" (the one you call operator== on) passed, making it 3 arguments instead of 2.

That being said, from the way you wrote the code I'm guessing you just forgot to put friend in front of the operator== declaration, in the class definition.

Probably useful tip: You can use #pragma once, on compilers that support it (basically every "main" compiler), instead of include guards. :)

Upvotes: 10

Chnossos
Chnossos

Reputation: 10506

Change your prototype to bool operator==(Duree const& rhs); or make it a free function out of class Duree.

Upvotes: 2

Related Questions