Accessing private variables of a class C++ - c++

Trying to overload the == operator, want to compare the hour, min, sec variables, but they're declared private and we've been told we're not allowed to adjust the header file. How do I access them in my code that is overloading the == operator? I also can't access them as h, m, s as they're called in the setTime method.
// using _TIMEX_H_ since _TIME_H_ seems to be used by some C++ systems
#ifndef _TIMEX_H_
#define _TIMEX_H_
using namespace std;
#include <iostream>
class Time
{ public:
Time();
Time(int h, int m = 0, int s = 0);
void setTime(int, int, int);
Time operator+(unsigned int) const;
Time& operator+=(unsigned int);
Time& operator++(); // postfix version
Time operator++(int); // prefix version
// new member functions that you have to implement
Time operator-(unsigned int) const;
Time& operator-=(unsigned int);
Time& operator--(); // postfix version
Time operator--(int); // prefix version
bool operator==(const Time&) const;
bool operator<(const Time&) const;
bool operator>(const Time&) const;
private:
int hour, min, sec;
friend ostream& operator<<(ostream&, const Time&);
// new friend functions that you have to implement
friend bool operator<=(const Time&, const Time&);
friend bool operator>=(const Time&, const Time&);
friend bool operator!=(const Time&, const Time&);
friend unsigned int operator-(const Time&, const Time&);
};
#endif
.cpp file
using namespace std;
#include <iostream>
#include <iomanip>
#include "Time.h"
Time::Time()
{ hour = min = sec = 0;
}
Time::Time(int h, int m, int s)
{ setTime(h, m, s);
}
void Time::setTime(int h, int m, int s)
{ hour = (h>=0 && h<24) ? h : 0;
min = (m>=0 && m<60) ? m : 0;
sec = (s>=0 && s<60) ? s : 0;
}
Time operator==(Time &t1, Time &t2)
{
return (t1.hour==t2.hour);
}

The == operator you're supposed to implement is a member function, so you should define
bool Time::operator==(const Time& t) const
{
return hour == t.hour && min == t.min && sec == t.sec;
}

Here is a trick:
bool operator==(Time &t1, Time &t2)
{
return !(t1 != t2);
}
bool operator!=(const Time& t1, const Time& t2)
{
return t1.hour != t2.hour || t1.min != t2.min || t1.sec != t2.sec;
}
You can't access your private fields in your operator== function. But since your operator!= is defined as friend, you can do it there.

Related

No match for operator "==" for nonmember operator overload

#include <iostream>
using namespace std;
class Test{
private: int cost{};
public:
Test(int value): cost{value}{}
int GetCost() const{return cost;}
bool operator >(const Test& rhs) const noexcept {return GetCost() > rhs.GetCost();}
bool operator>=(const Test& rhs) const noexcept {return (*this > rhs) || (*this == rhs;)}
};
bool operator==(const Test& a, const Test& b) noexcept
{
return a.GetCost() == b.GetCost();
}
int main()
{
cout<< (Test{2} >= Test{3});
return 0;
}
I get the following error for the code.
error: no match for ‘operator==’ (operand types are ‘const Test’ and ‘const Test’)
bool operator>=(const Test& rhs) const noexcept {return *this == rhs;}
What is the problem here? Is it not possible to mix member and non-member operator overloads?
You should also overload operator == in Test class.
class Test{
private:
int cost{};
public:
Test(int value): cost{value}{}
int GetCost() const{return cost;}
bool operator==(const Test& rhs) const noexcept {return GetCost() == rhs.GetCost();}
bool operator >(const Test& rhs) const noexcept {return GetCost() > rhs.GetCost();}
bool operator>=(const Test& rhs) const noexcept {return (*this > rhs) || (*this == rhs);}
};
So you can use it in your overloading and member functions like operator>=.
for more work you can do this:
bool operator==(const Test& a, const int& b) noexcept
{
return a.GetCost() == b;
}
And This:
bool operator==(const int& a, const Test& b) noexcept
{
return a == b.GetCost();
}
By doing so you can even use == as follows:
cout<< (Test{3} == 3);
cout<< (2 == Test{3});

STABLE_PARTITION problems: no matching function to call to "swap"

somehow I can't use stable_partition algorithm on
vector<pair<Class, string>>.
I can re-organize the code to get what I want, but for me (as I am new to C++) it's more "WHY" and not "HOW" question. will be glad if you clarify this behavior:
First, class Date (you can omit it and come look at it later):
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
class Date {
public:
Date(int new_year, int new_month, int new_day) {
year = new_year; month = new_month; day = new_day;
}
int GetYear() const {return year;}
int GetMonth() const {return month;}
int GetDay() const {return day;}
private:
int year, month, day;
};
bool operator<(const Date& lhs, const Date& rhs) {
return vector<int>{lhs.GetYear(), lhs.GetMonth(), lhs.GetDay()} <
vector<int>{rhs.GetYear(), rhs.GetMonth(), rhs.GetDay()};
}
bool operator==(const Date& lhs, const Date& rhs) {
return vector<int>{lhs.GetYear(), lhs.GetMonth(), lhs.GetDay()} ==
vector<int>{rhs.GetYear(), rhs.GetMonth(), rhs.GetDay()};
}
SO THIS IS THE CLASS WITH THE TROUBLE:
class Database {
public:
void Add(const Date& date, const string event){
storage.push_back(make_pair(date, event));
set_dates.insert(date);
}
void Print(ostream& s) const{
for(const auto& date : set_dates) {
// TROUBLE IS HERE:
auto it = stable_partition(begin(storage), end(storage),
[date](const pair<Date, string> p){
return p.first == date;
});
};
}
private:
vector<pair<Date, string>> storage;
set<Date> set_dates;
};
When compiled, it returns a lot of problems of same kind:
I've tried the same code on vector<pair<int, string>> (used stable_partition with lambda {return p.first == _int; } and it worked.
Would appreciate your help
The std::stable_partition function is supposed to modify the vector. However, you are calling it in a const member function, so storage is const there. This can't work.
Solution: Don't make Print const, or use std::stable_partition on a copy of storage. Neither is a great solution, so you should probably rethink your design.
You need to define overloading operator= for Date class as well. It will work if you do that stuff.
class Date {
public:
Date(int new_year, int new_month, int new_day) {
year = new_year; month = new_month; day = new_day;
}
// Need to define overloading operator=
Date& operator=(const Date& rhs)
{
}
int GetYear() const {return year;}
int GetMonth() const {return month;}
int GetDay() const {return day;}
private:
int year, month, day;
};

class method signature with *const* or without *const*?

I get the following error in Eclipse when trying to compile (c++)
../CardDeck.cpp:17:22: error: passing ‘const CardDeck’ as ‘this’ argument of ‘int CardDeck::size()’ discards qualifiers [-fpermissive]
if I change int size() method to int size() const the error msg is gone and its compiled. I dont know why ?
the .H file is the following :
#include "Card.h"
#include <vector>
using namespace std;
class CardDeck{
private:
vector<Card*> deck;
public:
int size();
CardDeck();
CardDeck(const CardDeck& rhs);
CardDeck& operator=(const CardDeck& rhs);
Card& draw();
Card& top();
bool isEmpty();
void clear();
int value();
CardDeck& operator+=(const CardDeck& rhs); /// not sure if to return ref
CardDeck& operator+(const CardDeck& rhs);
friend CardDeck& operator*(unsigned int num,CardDeck& rhs);
friend CardDeck& operator*(CardDeck& lhs,unsigned int num);
bool operator<=(const CardDeck& rhs );
bool operator>=(const CardDeck& rhs);
bool operator<(const CardDeck& rhs);
bool operator>(const CardDeck& rhs);
bool operator==(const CardDeck& rhs);
bool operator!=(const CardDeck& rhs);
Card* operator[](int i);
};
and the C++ file is :
#include "CardDeck.h"
int CardDeck::size() {
return this->deck.size();
}
CardDeck::CardDeck(){};
CardDeck::CardDeck(const CardDeck& rhs){
this->clear();
int i;
for (i=0;i<rhs.size();i++){
Card* current_card = rhs.deck[i];
Card* new_copy = new Card(*current_card);
this->deck.push_back(new_copy);
}
}
Card* CardDeck::operator[](int i) {
return this->deck[i];
}
void CardDeck::clear(){
vector<Card*>::iterator it ;
for(it=this->deck.begin();it != this->deck.end();++it){
Card* temp = *it;
this->deck.erase(it);
delete(temp);
}
}
In your copy constructor CardDeck::CardDeck(const CardDeck& rhs), rhs is a reference to a const CardDeck object.
So rhs.size() will not compile unless size() is explicitly marked as being const. That's what your compiler is telling you.
It's good practice to have your code as const-correct as possible as this prevents errant changes to the member data in a class. Really, isEmpty(), and possibly value() should be marked const too, as should all the overloaded relational operators.

How to initialize priority_queue of a class in C++?

I am trying to initialize a priority_queue , Here is the code
class stdnt{
public:
int indx;
int c;
int lvl;
bool operator<(const stdnt &x)
{
return this->c > x.c;
}
};
priority_queue<stdnt> pq;
But its giving me error that passing const & discards qualifiers. How else am I supposed to do this?
You need to make the operator const so that it can be called on const instances or via const references or pointers to const:
bool operator<(const stdnt &x) const
^^^^^
Alternatively, make it a non-member:
bool operator<(const stdnt &lhs, const stdnt& rhs)
{
return lhs.c > rhs.c;
}

Comparison operator overloading for a struct, symmetrically comparing my struct with an int type?

I'm trying to overload these operators:
<, <=, ==, >=, >, and maybe later !=,
in a struct.
It seems that comparing an object of the struct with another object of the same struct is easy, because when overloading the operator for that scenario, the definition is automatically symmetric.
But what if I want to compare my struct FOOD to an int?
This is also easy as long as FOOD comes first, however, what about the scenario when the int comes first? How do I define that without g++ giving me so many "must contain exactly one argument" errors?
I realize that
bool operator> (const int &, const FOOD &) const;
has problems due to the 'more than one argument' thing. I get that.
On all the forums I've search across the interwebs, everyone's solution seems to be using friend, but their difficulties are always in the context of classes, not structs. How is this done for s struct?
struct FOOD {
int foodID;
double price;
bool operator> (const FOOD &) const; //FOOD > FOOD
bool operator>=(const FOOD &) const; //FOOD >= FOOD
bool operator==(const FOOD &) const; //FOOD == FOOD
bool operator<=(const FOOD &) const; //FOOD <= FOOD
bool operator< (const FOOD &) const; //FOOD < FOOD
bool operator> (const int &) const; //FOOD > int
bool operator>=(const int &) const; //FOOD >= int
bool operator==(const int &) const; //FOOD == int
bool operator<=(const int &) const; //FOOD <= int
bool operator< (const int &) const; //FOOD < int
bool operator> (const int &, const FOOD &) const; // int > FOOD
bool operator>=(const int &, const FOOD &) const; // int >= FOOD
bool operator==(const int &, const FOOD &) const; // int == FOOD
bool operator<=(const int &, const FOOD &) const; // int <= FOOD
bool operator< (const int &, const FOOD &) const; // int < FOOD
};
bool FOOD::operator> (const FOOD &f) const {return foodID > f.foodID;}//FOOD > FOOD
bool FOOD::operator>=(const FOOD &f) const {return foodID >= f.foodID;}//FOOD >= FOOD
bool FOOD::operator==(const FOOD &f) const {return foodID == f.foodID;}//FOOD == FOOD
bool FOOD::operator<=(const FOOD &f) const {return foodID <= f.foodID;}//FOOD <= FOOD
bool FOOD::operator< (const FOOD &f) const {return foodID < f.foodID;}//FOOD < FOOD
bool FOOD::operator> (const int &i) const {return foodID > i;} //FOOD > int
bool FOOD::operator>=(const int &i) const {return foodID >= i;} //FOOD >= int
bool FOOD::operator==(const int &i) const {return foodID == i;} //FOOD == int
bool FOOD::operator<=(const int &i) const {return foodID <= i;} //FOOD <= int
bool FOOD::operator< (const int &i) const {return foodID < i;} //FOOD < int
bool FOOD::operator> (const int &i, const FOOD &f) const {return i > f.foodID;}// int > FOOD
bool FOOD::operator>=(const int &i, const FOOD &f) const {return i >= f.foodID;}// int >= FOOD
bool FOOD::operator==(const int &i, const FOOD &f) const {return i == f.foodID;}// int == FOOD
bool FOOD::operator<=(const int &i, const FOOD &f) const {return i <= f.foodID;}// int <= FOOD
bool FOOD::operator< (const int &i, const FOOD &f) const {return i < f.foodID;}// int < FOOD
g++ gives me these errors:
structsTransAndFood.cc:64:45: error: ‘bool FOOD::operator>(const int&, const FOOD&) const’ must take exactly one argument
Define it outside of the FOOD struct:
bool operator> (const int &i, const FOOD &f) {return i > f.foodID;}
Don't forget to remove this wrong declaration from the FOOD struct:
bool operator> (const int &, const FOOD &) const; // <--- remove it
and the corresponding definition:
bool FOOD::operator> (const int &i, const FOOD &f) const {return i > f.foodID;} // <--- remove it
Repeat the same for other operators.
Solution
You claim that you understand "more than one argument thing". However, it turns out that you don't. I don't get why you have troubles understanding what compiler and 2 people here tell you, but here is how the solution would look like:
struct FOOD {
int foodID;
double price;
bool operator> (const FOOD &) const;
bool operator>=(const FOOD &) const;
bool operator==(const FOOD &) const;
bool operator<=(const FOOD &) const;
bool operator< (const FOOD &) const;
bool operator> (const int &) const;
bool operator>=(const int &) const;
bool operator==(const int &) const;
bool operator<=(const int &) const;
bool operator< (const int &) const;
};
bool FOOD::operator> (const FOOD &f) const {return foodID > f.foodID;}
bool FOOD::operator>=(const FOOD &f) const {return foodID >= f.foodID;}
bool FOOD::operator==(const FOOD &f) const {return foodID == f.foodID;}
bool FOOD::operator<=(const FOOD &f) const {return foodID <= f.foodID;}
bool FOOD::operator< (const FOOD &f) const {return foodID < f.foodID;}
bool FOOD::operator> (const int &i) const {return foodID > i;}
bool FOOD::operator>=(const int &i) const {return foodID >= i;}
bool FOOD::operator==(const int &i) const {return foodID == i;}
bool FOOD::operator<=(const int &i) const {return foodID <= i;}
bool FOOD::operator< (const int &i) const {return foodID < i;}
bool operator> (const int &i, const FOOD &f) {return i > f.foodID;}
bool operator>=(const int &i, const FOOD &f) {return i >= f.foodID;}
bool operator==(const int &i, const FOOD &f) {return i == f.foodID;}
bool operator<=(const int &i, const FOOD &f) {return i <= f.foodID;}
bool operator< (const int &i, const FOOD &f) {return i < f.foodID;}
This type of operator
bool operator> (const int &, const FOOD &) const;
cannot be a member. A member function takes one extra, implicit parameter of type FOOD* (possibly cv qualified), so the example above actually takes three arguments. You need to make it a non-member.
I think the easiest approach would be to give your class an explicit int conversion operator
explicit operator int() const { return foodID; }
Also note that all the comparison operators can be expressed in terms of a single one, for instance bool operator< (this technique is used for example in std library associative containers)