Overloaded Equality Operator Question

In my program I am attempting to compare two "Contact" objects using the overloaded equality operator. I am clearly defining it wrong because in the "contains" function the compiler is saying "no match for operator==..."

Here is the header and definition of the equality operator:
1
2
3
4
5
6
  friend bool operator== (Contact& lhs, Contact& rhs);

bool operator==(Contact& lhs, Contact& rhs)
{
    return lhs==rhs;
}


And here is the function trying to use the equality operator:
1
2
3
4
5
6
7
8
9
10
11
12
13
bool Bag::contains(const Contact& anEntry)
{
    bool found;
    int index=0;

    while (!found && index < bagSize)
    {
        if (anEntry==arr[index])
            found = true;
        index++;
    }
return found;
}


arr[index} is a defined array of contacts in the class.

The point of the function is to compare if my class contains a contact object already or not. How do I make it so anEntry can be compared correctly to arr[index]?
Last edited on
Of course you're doing it wrong.
Firstly, why is this operator defined as friend?
And secondly; you expect it to work recursively? :)
If you have operator== for 2 contacts, you can't say "To compare two contacts, compare first contact to second one". That's like saying "Horse is a horse".
It should look more like this:
1
2
3
4
5
6
7
8
9
class Something
{
//code...
public:
bool operator==(Contact& other) const
{
//compare all elements, one by one...
}
};


It should work. If you are in doubt, you can check any tutorial site. I just found one:
http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html
Cheers! :)
Last edited on
Hmm. I'm not sure how strict the rules are for your compiler. According to the guidelines, the righthand side has to be declared as a const. And I would also try only allowing 1 parameter instead of two. So you'll have something like this:

1
2
3
4
5

friend bool operator==(const Contact &rhs){
    return (*this==rhs)
  
}


These are also really touchy so be sure to declare it in your header file and and not within the cpp implementation file. If it's outside the class don't forget to add "bool Contact::". I know some of these things seem obvious but it's clear that it's an issue with being able to see your function and probably not with the function itself.
Last edited on
Look at how you've defined your equality operator:

1
2
3
4
5
bool operator==(Contact& lhs, Contact& rhs)
{
    return lhs==rhs;
}

It does nothing but... call the equality operator for two Contact objects!

How can that operator be defined, when you're in the middle of defining it?
ok , thank you for the help thus far. I am using MatthewRock's definition but I am having trouble figuring out how to compare all the elements one by one. Isn't that what my function "contains" is supposed to do? Sorry, new to overloaded operators.
Last edited on
Your function "contains", if I'm right, is comparing all elements in bag. And bag is happening to have Contacts. So, if you want to compare contacts, first you have to define how to compare them!(in other words, how do you know that they're not the same). It's not the same as comparing all elements of class. I can't come up with anything better then simple example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Contact
{
    int age;
    int ID;
    std::string name;
//code...
public:
//code... with defined getters and setters(e.g. setAge, getAge)
bool operator==(Contact& other) const
{
   bool result = true;
   if( (age != other.getAge()) || (ID != other.getID()) || (name != other.getName()) )
       result = false;

   return result;
}
};

That should do it.

Cheers!
Last edited on
The logic to it is that there is a Bag class that holds an array of contacts. The only member variables are the array of Contacts and the size of the bag. The "contains" function is supposed to check if the Contacts array currently holds the Contact object in which I am passing to it.

Here is the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef BAG_H
#define BAG_H

#include <iostream>
#include "contact.h"

class Bag {
    friend std::ostream &operator<<(std::ostream &c, const Bag& bag);
private:
    static const int CAPACITY = 30;
    Contact arr1[CAPACITY];
    int bagSize;
public:
    Bag();
    bool add(const Contact& newEntry);
    bool contains(const Contact &anEntry);
    bool operator== (const Contact& rhs) const;
};

#endif


I am starting to understand it but not completely there yet. The "==" in the Contains function has a "anEntry" being compared to the array to see if it exists or not. How then, when it interacts with overloaded == operator does it work? I am simply trying to compare Contacts, that are members of the Bag class.

I'm probably not understanding something very simple. Thank for the help.
Yeah, you need to think about it the other way.

What line 17 means in your code is:

"I, Bag, can check if I am equal to the Contact called rhs."(and it can be checked by this code:
1
2
3
4
Bag bag;
Contact contact;
if(bag == contact)
    std::cout<<"Yay!";

However, two things will not work:
1)You want to be able to check if Contact1 is equal to Contact2
2)You want to be able to check if Contact2 is equal to Contact1

Both tests would fail the code above, but moreover, if I wrote it this way:
1
2
//code...
if(contact == bag) // Error! You don't have an bool Contact::operator==(Bag& other) const; ! 

You see? But yet you can do this:
1
2
3
int i, j;
i == j;
j == i;//both legit 

I don't want to be your tutorial book; if you read deeply about pointers, references and classes, then you should know that what I did with int was available to me thanks to references.

But, back to topic: how can you check if Contact1 is the same as Contact2?(and the other way?)
Well, let's go step by step.
It would be natural to write a simple function.
For clarity, let's define Contact class, and then our function. Also, for clarity, I will omit getters and setters; I will just make data public. You shouldn't do that, but you should already know it :)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Contact
{
  public:
  int ID;//Contact's ID
  int num;//Contact's telephone number
  std::string name;//Contact's name
  
  Contact(int id = 0, int nu = 555, std::string nam = "Tom") : ID(id), num(nu), name(nam)
  {}//Default and not default constructor
};
//Okay, so how do we check if both Contacts are the same? Simply check if their fields(ID, num, name) are the same:

bool AreContactsTheSame(const Contact& first, const Contact& second)
{
  bool result = true;
  if((first.num != second.num) || (first.name != second.name))//I skip ID, because the same person may occupy two fields in our database
     result = false;//If any of the fields isn't the same in both contacts, it means that contacts aren't the same

  return result;
}


Okay, that was pretty straightforward. But it would also be annoying as hell if you had to write AreContactsTheSame every time you want to compare 2 contacts, right? That's when we go to definition of Contact, and add an == operator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//I just copied class definition from above and added operator

class Contact
{
  public:
  int ID;//Contact's ID
  int num;//Contact's telephone number
  std::string name;//Contact's name
  
  Contact(int id = 0, int nu = 555, std::string nam = "Tom") : ID(id), num(nu), name(nam)
  {}//Default and not default constructor

  bool operator== (Contact& other) const
  {
    return AreContactsTheSame(*this, other);
  }
};

That's it. Notice that we don't need 2 arguments, since you call it like this:
 
contact1 == contact2

So actually you can interpret it like that:
 
contact1.operator==(contact2);


Simply you have to understand, that Contact has to know how to compare itself to other contact. Bag shouldn't care about how Contact looks inside. It should have right tools to do the job, the same way as you don't define any operator== for int or double - you already have it included. And it's the int's job to know how to check if it's equal to other int.

Also, notice that previously I said that you compare "all member data", but now I didn't do it. I did not lie to you previously(well, not too much); simply when you start, and overally quite often when you program, one class is the same as other if it has all fields the same. However, sometimes it doesn't. You had an example right here - if there was a field 0 with John Smith with phone 5234, and field 538 with same John Smith with same number(because he probably had two companies, or whatever). But it's up to you to define rules to check if 2 inputs are the same.

Cheers!

PS. And sorry for it, but I did forgot one thing(and it's wiser to mention it as PS then edit code): every time you're defining an operator==, you may want to add this in the beginning:
1
2
3
4
5
bool operator==(someclass& other) const
{
   if(this == &other)
     return true;
}

It does not mean anything more than "If I am comparing myself to myself, then I'm the same as me". So, comparing a to a should always yield true. And if you had a large class with thousands of member data, comparing one to itself could be pretty much expensive, not mentioning pointless.

Cheers!
Last edited on
ok gotcha, now I understand. thanks.
Glad I could help :) If you have no more questions, you can change topic's icon(most likely by editing first post) to "Solved", so if others have similar problem, they will know this case was solved in this thread.

Cheers!
Topic archived. No new replies allowed.