Overloading comparison operators - c++

I'm having trouble overloading the comparison operators > and <. I've tried two different ways but I'm still having trouble.
bool Car::operator ==(const Car &car)
{
return mLNumber == car.GetNum();
}
bool Car::operator <(const Car &carB)
{
return mLNumber < carB.GetNum();
}
bool Car::operator >(const Car &carB)
{
return mLNumber > carB.GetNum();
}
int Car::GetNum()
{
return mLNumber;
}
My == operator works just fine. I get the error that these operators don't exist. Here is my 2nd attempt.
bool Car::operator <(const Car &carA, const Car &carB)
{
return carA.GetNum() < carB.GetNum();
}
bool Car::operator >(const Car &carB)
{
return carA.GetNum() > carB.GetNum();
}
And I get the error that there are too many parameters. I also get this:
'Car::GetNum' : cannot convert 'this' pointer from 'const Car' to 'Car &'

Try making your operators const:
bool Car::operator <(const Car &carB) const {
return mLNumber < carB.GetNum();
}
bool Car::operator >(const Car &carB) const {
return mLNumber > carB.GetNum();
}
Edit: And in this case, you should make the GetNum() function as const too because you are calling it on const Car& objects.
You don't need GetNum() either, you could just write
bool Car::operator <(const Car &carB) const {
return mLNumber < carB.mLNumber;
}

There's two problems in the code - first, logically, your operators are immutable on the type - they don't change the objects, they only analyze them, and you should be able to call them on immutable (const) objects. So, as alestanis pointed out, make them const (all operators and the getter method).
Second, < == and > are binary operators. There's two options to implement them: as free operators, or as members. You went with members, which is okay, but:
bool Car::operator <(const Car &carA, const Car &carB)
doesn't declare a binary operator. When you implement an operator as a member, the first parameter is implicitly the current object (*this), so it should be
bool Car::operator <(const Car &carB) const
The free operator would look like:
bool operator < (const Car& carA, const Car& carB);
Note that const on this one doesn't make sense since it's not a member. However, note that the first parameter (carA) is marked as const, which corresponds to the const applied to the method in the member version (which, under the hood, marks this as const).

It would help to see where you're calling these operators.
Your second version with two Car arguments should be global operators. So drop the Car:: from the definitions if you use them. Move the declarations out of the Car class' body, too.
Since your calling GetNum on a const Car object, the Car::GetNum function also needs to be const. The dirtier way to do this is to cast away the const-ness, but that is frowned upon.

Your error is when you want to compare one const object and you operators is not marked asconst, as a general rule, you should always mark functions and operators that do not change your object as const and this make life much easier. For example:
bool Car::operator ==(const Car &car) const // <-- This function is const
{
return mLNumber == car.GetNum();
}

The problem is that car::GetNum() isn't declared const, so you can't call it on const instances of car. The operators take a const Car &carB as argument, so you can't call GetNum() on carB, since carB is a const object, but GetNum() has not been declared const.
You should get into the habit of declaring all functions that don't modify the object as const. To declare a function as const, simply append const after the closing parenthesis. Both in the declaration, as well as the definition. For example:
class car {
// ...
void car::foo() const;
// ...
};
void car::foo() const
{ /* ... */ }
Or, if you're defining it inline inside the class declaration:
class car {
// ...
void car::foo() const
{ /* ... */ }
// ...
};
Although not strictly necessary in this particular case (meaning this isn't why the code doesn't compile), the operators themselves should also be declared const for the same reason (so that you can use them also on const objects.)

In the first case:
Your operators do not change data of operands, then it should be made const:
bool Car::operator <(const Car &carB) const {
//^^^^^
return mLNumber < carB.GetNum();
}
bool Car::operator >(const Car &carB) const {
// ^^^^^
return mLNumber > carB.GetNum();
}
int Car::GetNum() const
//^^^^^
{
return mLNumber;
}
In the second case, when operators accept 2 arguments, they should be implemented as free functions:
bool operator <(const Car &carA, const Car &carB)
{
return carA.GetNum() < carB.GetNum();
}
bool operator >(const Car &carA, const Car &carB)
{
return carA.GetNum() > carB.GetNum();
}

Related

Creating a set of classes

I'm trying to create a set that can be filled with instances of a class. I thought that a requirement for a set is that elements can be compared, and thus in this case I need to tell my class how they can be compared. I created the following class:
class Myclass
{
public:
Myclass(int i):storedval(i) {}
int getval(){return storedval;}
friend bool operator> (Myclass &first, Myclass &second)
{
return first.getval()>second.getval();
}
friend bool operator< (Myclass &first, Myclass &second)
{
return first.getval()<second.getval();
}
private:
int storedval;
};
But when I try to add instances to a set like this:
Myclass a(50);
set<Myclass> Bunchofclasses;
Bunchofclasses.insert(a);
It gives me a bunch of error text that I think tells me it doesn't understand the > and < operators. How should this be done properly?
You need to pass const references to the comparison function because it should not be allowed to modify the items being compared:
friend bool operator< (const Myclass& first, const Myclass& second)
{ // ^^^^^ ^^^^^
return first.getval() < second.getval();
}
This will require that you make getVal() const as well. This makes it callable on const instances or via const references:
int getval() const {return storedval;}
// ^^^^^
Note that you do not need operator> for the set to work. Less-than is enough.
Strictly speaking, you do not need a friend function here, since you are calling public member functions. The only thing that friend brings here is to allow you to declare a non-member function inside of the class definition.
Elements of a set are immutable, so the set needs to be able to compare const values. So the comparison needs to be:
friend bool operator< (Myclass const &first, Myclass const &second)
// ^^^^^ ^^^^^
(You should probably also do this with operator> and any other non-mutating operations you provide; but set only needs operator<).
Also, in order to access the value of a const object, the accessor also needs to be const:
int getval() const
// ^^^^^

C++ overloading operator< error

Why am I receiving an error when I do not put const in the function bool operator<(const Node& otherNode) //const?
stl_algo.h:91: error: passing 'const Node' as 'this' argument of 'bool Node::operator<(const Node&)' discards qualifiers
Should all the overloaded operators be constant?
class Node {
public:
double coordinate;
bool operator==(const Node& other) const{
return coordinate == other.coordinate;
}
bool operator<(const Node& other) const{
return coordinate < other.coordinate;
}
};
Not all operators, but == and < should definitely be made const, yes. They logically don't modify either of the objects being compared.
The error likely comes from calling a non-const method from a const one, e.g.:
bool isSmaller(const Node& other) const
{
return *this < other;
}
In this case, since the method isSmaller is const, this is implicitly a const object, therefore operator < also has to be const in order for the call within that context to be valid.
From the error message, it appears that Node::operator < is being called on a const object, from a function in stl_algo.h - sorting/ordering functions, hashing functions, etc.
Comparison operators, such as <, >, <=, >=, ==, != should operate on const objects in general, because it makes no sense if any objects being compared can be changed by the comparison. But you could declare the comparisons as non-member functions in order to ensure symmetry between both operands.
class Node {
public:
double coordinate;
};
inline operator<(const Node& lhs, const Node& rhs)
{
return lhs.coordinate < rhs.coordinate;
}
Have you try to delete the const modifier of the method? Also, as #LuchianGrigore sugest, you can use the this keyword:
bool operator< (const Node& other) {
return this.coordinate < other.coordinate;
}

Use of operator overloading in structure within class

I have a header file where i am declaring a class with a structure within it. Also i am declaring an overloading operator(!=, to compare structures) as member of this class. I am giving the definition of this operator in the cpp file. But i am not able to access the members of the structure
car.h
class car
{
int carsor;
struct model
{
int id;
int mode;
}prev,curr;
bool operator !=(const model& model1);
};
car.cpp
#include "car.h"
bool car::operator !=(const model& model1)
{
if((model1.id==model.id)&&(model1.mode==model.mode))
{
return false;
}
else
{
return false;
}
}
The error i get is this
Error 2 error C2275: 'car::model' : illegal use of this type as an expression
how should i access the the structure members?
if((model1.id==model.id)&&(model1.mode==model.mode)) - model is the name of your class and not your object. Your object is accessible via this or you may omit it altogether inside the class.
Use if((model1.id==prev.id)&&(model1.mode==prev.mode)) to compare with prev or if((model1.id==next.id)&&(model1.mode==next.mode)) to compare with next.
This:
bool car::operator !=(const model& model1)
{
is a method comparing a car to a model. This, however:
bool car::model::operator != (car::model const &other) const
{
return !(*this == other);
}
is a method comparing two models (I've written it here as a method of car::model, but it could be a free function if you prefer.
I've also written it in terms of operator==, because the logic almost always works out easier:
bool car::model::operator ==(car::model const &other) const
{
return (this->id == other.id) && (this->mode == other.mode);
}
These methods would be declared as:
class car
{
struct model
{
int id;
int mode;
bool operator==(model const&) const;
bool operator!=(model const&) const;
// ...

Error using std::find with operator==

I am getting an error using std::find on the following structure ...
struct ComplianceOrderRecord {
explicit ComplianceOrderRecord(IOrder& order);
bool operator ==(const ComplianceOrderRecord& other) const;
double price;
};
inline bool ComplianceOrderRecord::operator ==(const ComplianceOrderRecord& other) const {
return price == other.price;
}
I use it as follows...
inline void Compliance::RemoveComplianceOrderRecord(const ComplianceOrderRecord& order) {
auto it = std::find(m_compliantOrderList.begin(),
m_compliantOrderList.end(), order);
if(it == m_compliantOrderList.end()) {
return;
}
m_compliantOrderList.erase(it);
}
The error is...
error C2679: binary '==' : no operator found which takes a right-hand operand of type 'const ComplianceOrderRecord' (or there is no acceptable conversion)
Any help in understanding this error would be very appreciated.
Your operator== should be a const member, or even better, a freestanding function.
This error can be reproduced if m_compliantOrderList is not a container<ComplianceOrderRecord >. (Perhaps it is a container of pointers, or some other completely unrelated class.
Edit:
Your equality operator can compare two instances of ComplianceOrderRecord, but find needs to compare a pointer against an object. Overloading an operator to perform this kind of comparison would be bizarre, so you could use find_if with a custom predicate, such as:
struct RecordIsEqualTo
{
const ComplianceOrderRecord* record;
RecordIsEqualTo(const ComplianceOrderRecord& r): record(&r) {}
bool operator() (const ComplianceOrderRecord* r) const { return *record == *r; }
};
std::find_if(m_compliantOrderList.begin(), m_compliantOrderList.end(),
RecordIsEqualTo(order) );
or a lambda version thereof.
Your operator== function should be const. As it is, you can't call it on a const object (or a reference to const.
Try a const method:
inline bool ComplianceOrderRecord::operator ==(const ComplianceOrderRecord& other) const {
return price == other.price;
}

Overloading = in C++

I'm trying to overload the assignment operator and would like to clear a few things up if that's ok.
I have a non member function, bool operator==( const MyClass& obj1, const myClass& obj2 ) defined oustide of my class.
I can't get at any of my private members for obvious reasons.
So what I think I need to do is to overload the assignment operator. And make assignments in the non member function.
With that said, I think I need to do the following:
use my functions and copy information using strcpy or strdup. I used strcpy.
go to the assignment operator, bool MyClass::operator=( const MyClass& obj1 );
Now we go to the function overloading (==) and assign obj2 to obj1.
I don't have a copy constructor, so I'm stuck with these:
class Class
{
private:
m_1;
m_2;
public:
..
};
void Class::Func1(char buff[]) const
{
strcpy( buff, m_1 );
return;
}
void Class::Func2(char buff[]) const
{
strcpy( buff, m_2 );
return;
}
bool Class& Class::operator=(const Class& obj)
{
if ( this != &obj ) // check for self assignment.
{
strcpy( m_1, obj.m_1 );
// do this for all other private members.
}
return *this;
}
bool operator== (const Class& obj1, const Class& obj2)
{
Class MyClass1, MyClass2;
MyClass1 = obj1;
MyClass2 = obj2;
MyClass2 = MyClass1;
// did this change anything?
// Microsofts debugger can not get this far.
return true;
}
So as you can probably tell, I'm completely lost in this overloading. Any tips? I do have a completed version overloading the same operator, only with ::, so my private members won't lose scope. I return my assignments as true and it works in main. Which is the example that I have in my book.
Will overloading the assignment operator and then preforming conversions in the operator== non member function work? Will I then be able to assign objects to each other in main after having completed that step?
You have a couple of obvious mistakes here and there is some confusion about what you are actually trying to achieve. Firstly, the assignment operator operator = is meant to copy the value from one instance to another. The return value of the assignment operator is almost always a non constant reference to the target of the copy, so that you can chain assignments:
Class & operator=(const Class &rhs)
{
// copy the members
return *this;
}
The comparison operator operator == is meant to perform a comparison of two instances. It returns a boolean true if they are equal:
boolean operator==(const Class &rhs) const
{
// check if they are equal
return something;
}
The confusion is why are you trying to copy values around, or maybe assign to the instances in the comparison operator?
Op== isn't the assignment operator. T& Op= (const T&) is.
bool operator==(const T& lhs, const T& rhs) is the operation to compare two Ts. It returns true if lhs is equal to rhs, for whatever definition of "equal" you want to code.
I am guessing that you want to compare the two objects. In that case, you can just overload the operator == in class "Class". You don't need assignment operator.
class Class
{
public:
Class(int i) : m_i(i){}
bool operator==( const Class& rhs)
{
return m_i == rhs.m_i;
}
private:
int m_i;
};
int main()
{
Class t1(10), t2(10);
bool b = (t1 == t2);
}
I am not sure whether I understood the question correctly. But if you trying to check the equality using a non-member function and can't do this only because you can't access the private members of the class, then you can declare the non-member function as a friend function and use it like this:
class Test
{
public:
Test(int i) : m_i(i){}
private:
int m_i;
friend bool operator==(Test& first, Test& second);
};
bool operator==(Test& first, Test& second)
{
return first.m_i == second.m_i;
}
int main()
{
Test t1(10), t2(10);
bool b = (t1 == t2);
}