Overloading the comparison operator for object members - c++

Say I have a class called book:
class Book {
int i;
public:
Book(int ii)
: i(ii) {
}
int ISBN() {
return i;
}
};
I want to overload the comparison operator for the Book class, so that I can create a bool function that will compare the member "i" when it comes across book1==book2.
bool is_same() {
return (book1==book2) ? true : false;
}
How would I go about this? This is the current operator overload function I have, it gives me an "invalid initialization of non-const reference of type 'Book&' from an rvalue of the type 'bool'" error. I currently have my overloaded function inside of the class Book as a public function.
Book& operator==(const Book& b) const {
return ISBN() == b.ISBN();
}
I'm relatively new to operator overloading, I have sifted through many answers but none of them resolve my issue. I understand how one could simply do book1==book2, but that would only return true if every single member was of the same value. In this case I have more than just one, but I only want to return true if "i" is the same for both objects.

You basically have 2 choices:
use a member operator with one argument:
class Book {
...
bool operator==( const Book &an ) const { return ISDN() == an.ISDN(); }
};
use a non-member operator (and possibly a friend statement) with 2 arguments:
bool operator==( const Book &b1, const Book &b2 )
{
return b1.ISBN() == b2.ISBN();
}
Note that ISDN() should be made const.
Either way, you need to return a bool, not a Book &, which is usually returned by the assignment operator =, not the comparison operator ==.

Related

Overloading the == operator

I am trying to compare member variables of 2 objects from the same class
in Donor.h
friend bool operator==(const Donor& donor1,const Donor& donor2);
And in Donor.cpp
bool Donor::operator==(const Donor& donor1, const Donor& donor2)
{
if (donor1.get_type() == donor2.get_type())
{
return true;
}
else
return false;
}
but i get an comple error
bool Donor::operator==(const Donor& donor1, const Donor& donor2) must have exactly one argument.
What am I doing wrong?
A friend function is not a member function. It cannot be defined as Donor::operator==, it must be just operator==.
The error message is less than helpful here. It is saying that a operator== member function only takes a single argument, but since you do not want to make it a member function, that is information you do not need.

Comparing two objects of the same class

I am trying to overload the == operator in C++.
#include <string>
using namespace std;
namespace date_independent
{
class clock
{
public:
int clockPair[2] = {0,0};
operator string() const
{
string hourString;
string minString;
if(clockPair[0]<10)
{
hourString = "0"+to_string(clockPair[0]);
}
else
{
hourString = to_string(clockPair[0]);
}
if(clockPair[1]<10)
{
minString = "0"+to_string(clockPair[1]);
}
else
{
minString = to_string(clockPair[1]);
}
return hourString+":"+minString;
};
bool operator ==(const clock&clockOne, const clock&clockTwo) const
{
return string(clockOne)==string(clockTwo);
};
};
};
There is much more code than I have included, but this is the important part. I want it so that the == operator can compare two objects of class clock. E.g., object1==object2. Is there anybody that can help me?
A binary operator like == can be overloaded either as a member function with a single parameter (this being the left-hand operand, and the parameter being the right-hand one), or as a non-member function with two parameters for the two operands.
So either
move your operator declaration outside the class declaration (moving the definition to a source file, or declaring it inline if you keep the definition in the header); or
add friend to the definition, so that it declares a non-member in the surrounding namespace; or
remove the first argument from the member function, using this instead.
As a member, it would look like
bool operator==(const const & clockTwo) const {
return string(*this) == string(clockTwo);
}
You might also want to compare the two integer values directly to save the expense of making strings. You should also remove the rogue ; after the function and namespace definitions, although most modern compilers shouldn't object to their presence.
Your comparison function has been written to take two clock objects and compare them, so it should be a non-member function (after the class definition), without the const qualifier.
bool operator==(const clock& clockOne, const clock& clockTwo)
{
return string(clockOne) == string(clockTwo);
}
When you have an operator inside the class definition, the left-hand argument is implicitly provided for you (it's *this), so if you wanted to implement it there you'd need something like:
bool operator==(const clock& clockTwo) const
{
return string(*this) == string(clockTwo);
}
Still, that's not recommended for == as if you have say an implicit constructor from another type T, you won't be able to write code ala my_t == my_clock with the member version unless T provides a suitable comparison operator (for clock or string). A non-member operator gives more symmetric operation.
Overloading can be done inside or outside the class definition. If you want to do it inside, the function receives only one argument. You should compare this with that argument.
bool operator ==(const clock&clockTwo) const
{
return string(*this)==string(clockTwo);
}
Note the const after the argument, it means that you won't change this inside the function.
On the other hand, if you want to do it outside the class definition, it needs two arguments, and you should compare them.
bool operator ==(const clock&clockOne, const clock&clockTwo)
{
return string(clockOne)==string(clockTwo);
}
Also note that it'll be faster to compare the clockPair of the objects rather than making the string and comparing them.
Though your question is poorly worded I believe that you are asking why the operator you've defined is not working?
If you are defining the operator as a member of the class it only takes one parameter. For example:
class clock {
bool operator ==(const clock& rhsClock) const
{
// Note: this is the lhsClock
return string(*this) == string(otherClock);
}
};
When you define the operator as a free function (not as a part of the class) then you need to define both parameters:
class clock {
// ... class declaration ...
};
bool operator ==(const clock& lhsClock, const clock& rhsClock)
{
return string(lhsClock) == string(rhsClock)
}
Where the comparison would look like this:
if (lhsClock == rhsClock) // ... do something ...

Calling superclass method operator== [duplicate]

This question already has answers here:
How to call a parent class function from derived class function?
(7 answers)
Closed 8 years ago.
I'm going through a transition from Java to C++ and am trying to write a simple program.
There's a superclass Animal with the following inteface:
class Animal
{
public:
Animal(int a, std::string n);
bool operator==(Animal a);
private:
int age;
std::string name;
};
And it's subclass Dog:
class Dog : public Animal
{
public:
Dog(int a, std::string n, double w);
bool operator==(Dog d);
private:
double weight;
};
My question is in regards to the Dog's operator== method, which compares 2 dogs.
Animal's operator== is below.
bool Animal::operator==(Animal a) //overriding of operator ==
{
return (age==a.age) && (name==a.name);
}
Now I want to write the Dog's version using Animal's method.
Like I'd do in Java:
boolean equals(Dog d){
return (super.equals(d)) && (this.name==d.name);
}
What I need is the c++ equivalent of (super.equals(d)) . If it was a method with a normal name it would be easy(Animal::equals(d)), but I don't know how to do it for operator==, which has a diferent syntax.
It's actually surprisingly easy:
return Animal::operator==(d) && name==d.name;
The reason for using the superclass' name rather than super is that in C++ you can have multiple superclasses, so you have to be clear about which one you want.
Alternatively, you can call it via using it's overload:
return ((Animal&)*this)==d && name==d.name;
Since the paramters to operator== in this case would be an Animal& and a Dog&, then it can't match Dog::operator==(Dog d), and so uses Animal::operator==(Animal a) instead.
Note: Your signatures are highly unusual. Instead, use one of these:
bool operator==(const Animal& a) const;
friend bool operator==(const Animal& left, const Animal& right);
These don't make copies of animals each time you compare, and can compare const animals.
You can call the operator using verbose notation:
operator==(const Dog& dog) { return Animal::operator==(dog) && weight==dog.weight; }
The direct equivalent of your Java equals would be:
bool Dog::operator==(Dog d)
{
return Animal::operator==(d) && weight == d.weight;
}
But I'm not sure if this is what you really want. For starters,
you're taking the argument by copy, which means that your
comparing a copy. In particular, when you call
Animal::operator==, you will pass a copy of the Animal part
of Dog, not the complete object. Class types are usually
passed by reference; reference to const if you don't want to
modify them. So the signature in the base would be something
like:
bool Animal::operator==( Animal const& other ) const
{
// ...
}
And similarly in Dog. Also, the comparison operator in Dog
would probably take an Animal const&, not a Dog const&. (In
Java, equals takes a java.lang.Object, always.) Which means
that you'd have to verify that it was a Dog:
bool Dog::operator==( Animal const& other ) const
{
return dynamic_cast<Dog const*>( &other ) != nullptr
&& Animal::operator==( other )
&& weight == other.weight;
}
EDIT:
As was pointed out in a comment, while this addresses the
immediate syntax issue raised by the original poster, it isn't
really the way we'd do this normally. The usual solution would
be something like:
class Animal
{
// If Animal is actually an abstract class (usually the case
// in real code), this would be a pure virtual.
// Derived classes overriding this function are guaranteed
// that other is actually of the same type as they are,
// so they can just static_cast it to their type.
virtual bool doIsEqual( Animal const& other ) const
{
return true;
}
public:
bool isEqual( Animal const& other )
{
return typeid( *this ) == typeid( other )
&& // ... his local conditions...
&& doIsEqual( other );
}
};
bool operator==( Animal const& lhs, Animal const& rhs )
{
return lhs.isEqual( rhs );
}
bool operator!=( Animal const& lhs, Animal const& rhs )
{
return !lhs.isEqual( rhs );
}
The implementation of operator== and operator!= can in fact
be done by inheriting from an appropriate class template, which
avoids some of the boilerplate if you have a lot of classes
which must support == and the others.

`bool operator<(Contact&)' must take exactly two arguments

I have
class Conatact{
.....
bool operator<(Contact &c);
};
bool operator<(Contact &c)
{
return this.getName<c.getName();
}
it says `bool operator<(Contact&)' must take exactly two arguments
when I try to change it to have two arguments
bool operator<(Contact &c)
{
return this.getName<c.getName();
}
it says it must take exactly one argument
I think you need to indicate to the compiler it's a member implementation by supplying a fully qualified name:
bool Conatact::operator<(Contact &c)
{
return this->getName() < c.getName();
}
It would be a good idea to make your operator const, and to make the Contact &c const as well.
Without the scope resolution qualifier, the compiler thinks that you are defining a "free-standing" operator to compare contacts, in which case the operator would indeed need to take two arguments:
bool operator<(const Contact &lhs, const Contact &rhs) {
...
}

Is there an equivalent of the Java equals method in c++?

Is there something like Java equals()? To compare if object is the same type ?
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof ViewMode)) {
return false;
}
ViewMode dm = (ViewMode) obj;
return dm.width == w
&& dm.h == h
&& dm.b == b
&& dm.f == f;
}
public int hashCode() {
return w ^ h ^ f ^ b ;
}
For the idiomatic equivalent of your example, you would define operator== as follows:
friend bool operator==(const ViewMode &lhs, const ViewMode &rhs) {
return (lhs.w == rhs.w) && the rest;
}
friend bool operator!=(const ViewMode &lhs, const ViewMode &rhs) {
return !(lhs == rhs);
}
In C++ you don't normally write a function to allow ViewMode objects to be compared with something that has nothing at all to do with ViewMode. I suppose that if you really wanted that comparison to return false, rather than refusing to compile, then you could add a couple of template operators (as free functions, outside the class):
template <typename T>
bool operator==(const ViewMode &, const T&) {
return false;
}
template <typename T>
bool operator==(const T &, const ViewMode&) {
return false;
}
but I really don't recommend it. That Java idiom doesn't apply to C++, because in C++ you pretty much should never have an object, but have no idea of its type.
If you want your equals function to be virtual, then it's probably best to write an equals() virtual function, rather than using operator== for it. You'd write it to take a const ViewObject & as parameter, so no need for any equivalent to the instanceof check. Which is just as well, because C++ does not have any way to take an object of totally unknown type and test whether it is an instance of a specified type.
You rarely need a polymorphic equals function in C++, but if you were using it for example in std::unordered_map, then you'd specify the extra template parameters to the unordered_map. Give it an equality comparison function that takes two pointers and calls equals on one or the other, and a hash function that does something sensible.
No. C++ does not have a global type model like Java. There is no Object type from which all other types inherit, so there are no methods (like equals) that are defined for all classes.
C++ provides a framework for building a type model with a universal comparison operation: operator ==. It is up to you to build out all of the implementations of this in all of your classes so that they interact correctly. But there is no default implementation comparable to Object.equals.
You can define the operator== in your class.
You might be able to use the typeid operator for this.