class method signature with *const* or without *const*? - c++

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.

Related

Binary operator overloading with class and constant in C++

I am trying to do operator overloading
My header is:
class Nyble
{
public:
Nyble();
Nyble(const Nyble& n);
Nyble& operator=(const Nyble& n);
~Nyble();
Nyble operator+(const char a);
Nyble operator-(const char a);
Nyble operator+(Nyble& n1);
Nyble operator+();
unsigned char getData();
private:
// Do not change this data
unsigned char data;
}
Source:
#include "Nyble.h"
unsigned char Nyble::getData()
{
return this->data;
}
Nyble Nyble::operator+(const char val)
{
return Nyble(getData()+val);
}
Nyble Nyble::operator-(const char value)
{
return Nyble(value + getData()) ;
}``
I am getting an error saying no suitable constructor exists to convert int to Nyble. If so, what constructor should I declare? Else what changes should I make to the overloading function?
You need to add a constructor for Nyble(getData() + val); and Nyble(value + getData()) to work:
class Nyble {
public:
explicit Nyble(char d); // add this
// ...
};
Nyble::Nyble(char d) : data(d) {} // and the implementation
Though, I recommend that you instead implement operator+ and operator- as free functions and make operator+= and operator-= member functions.
It could look like this:
class Nyble {
public:
Nyble() = default;
explicit Nyble(unsigned char d);
// implement operator+= and operator-= as member functions
Nyble& operator+=(const Nyble& n1);
Nyble& operator-=(const Nyble& n1);
unsigned char getData() const;
unsigned char& getData();
private:
unsigned char data = 0;
};
// operator+ and operator- as free functions:
Nyble operator+(Nyble lhs, const Nyble& rhs);
Nyble operator-(Nyble lhs, const Nyble& rhs);
Nyble::Nyble(unsigned char d) : data(d) {}
// the implementation of the member operator overloads:
Nyble& Nyble::operator+=(const Nyble& rhs) {
data += rhs.data;
return *this;
}
Nyble& Nyble::operator-=(const Nyble& rhs) {
data -= rhs.data;
return *this;
}
unsigned char Nyble::getData() const { return data; }
unsigned char& Nyble::getData() { return data; }
// now the free functions can use the member functions
// `operator+=` and `operator-=`:
Nyble operator+(Nyble lhs, const Nyble& rhs) {
return lhs += rhs;
}
Nyble operator-(Nyble lhs, const Nyble& rhs) {
return lhs += rhs;
}

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

Why do I need to make this non friend == operator overload a member function to avoid "undefined reference" errors?

I have the following class, it is defined like so:
namespace ns{
class Bit{
public:
explicit Bit(bool bit);
Bit() = default;
explicit operator bool () const;
[[nodiscard]]
bool value() const;
[[nodiscard]]
Bit operator==(const Bit& rhs) const;
//friend Bit operator==(const Bit &lhs, const Bit &rhs); also doesn't work
private:
bool m_bit;
};
//doesn't work
//[[nodiscard]]
//Bit operator==(const Bit &lhs, const Bit &rhs);
}
When I define the operator == overload as a standalone function, it doesn't work, I get
undefined reference to `ns::operator==(ns::Bit const&, ns::Bit const&)'
Similar story for the friend function version.
The definition of the standalone function is as follows in the .cpp file:
ns::Bit operator==(const ns::Bit &lhs, const ns::Bit &rhs) {
return ns::Bit(lhs.value() == rhs.value());
}
The definition of the member function, which works, is as follows
ns::Bit ns::Bit::operator==(const ns::Bit &rhs) const{
return Bit(value() == rhs.value());
}
Why am I being forced to make a member function?
ns::Bit ns::operator==(const ns::Bit &lhs, const ns::Bit &rhs) {
return ns::Bit(lhs.value() == rhs.value());
}
you prototyped ns::operator== then defined ::operator==.
Only ns::operator== is found via ADL. ::operator== may also be found depending on what other == operators and what namespace you are in, adding confusion.

How to resolve a series of errors about iterator constructors involving expected l-values, missing conversions, and viability

I have a program I wrote for a class back in 2000 that I thought I would try to run just for the fun of it. It used to compile back in 2000, but I'm getting a bunch of errors now. I pretty much haven't looked at C++ code since that class, so I'm a bit bewildered. I resolved a bunch of complaints about iostream.h & list.h (putting "std::" in front of a bunch of things like std::cerr, etc). I don't know if that caused the current errors, or whether there's something inherently wrong with my iterators, but the only thing left to resolve involves a bunch of iterator constructors. First, here is a sample of the errors:
SolutionList.cpp:10:22: error: no matching constructor for initialization of 'PieceList::iterator'
PieceList::iterator i=rhs.first();
^ ~~~~~~~~~~~
./PieceList.h:27:5: note: candidate constructor not viable: expects an l-value for 1st argument
iterator(iterator& rhs){data = rhs.data;}
^
./PieceList.h:28:5: note: candidate constructor not viable: no known conversion from 'PieceList::iterator' to 'std::list<Piece>::iterator &'
(aka '__list_iterator<value_type, __void_pointer> &') for 1st argument
iterator(std::list<Piece>::iterator& rhs){data = rhs;}
^
./PieceList.h:26:5: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
iterator(){}
^
And here's what I believe is the relevant portion of code:
class PieceList
{
public:
PieceList(){}
PieceList(PieceList& rhs){pieces = rhs.pieces;}
PieceList(std::list<Piece>& rhs){pieces = rhs;}
friend std::ifstream& operator>>(std::ifstream&,PieceList&);
friend std::istream& operator>>(std::istream&,PieceList&);
class iterator
{
public:
friend class PieceList;
iterator(){}
iterator(iterator& rhs){data = rhs.data;}
iterator(std::list<Piece>::iterator& rhs){data = rhs;}
Piece operator*(){return *data;}
iterator& operator=(iterator& rhs){data=rhs.data;return *this;}
iterator& operator=(std::list<Piece>::iterator& rhs){data = rhs;return *this;}
bool operator==(iterator& rhs){return data==rhs.data;}
bool operator==(const iterator& rhs) const{return data==rhs.data;}
bool operator!=(iterator rhs){return data != rhs.data;}
iterator& operator++(){++data;return *this;}
iterator& operator--(){--data;return *this;}
private:
std::list<Piece>::iterator data;
};
iterator first(){iterator i;i.data=pieces.begin();return i;}
iterator last(){iterator i;i.data=pieces.end();return i;}
private:
std::list<Piece> pieces;
};
So I know that it doesn't like the second constructor, but I'm not sure how to fix it. I couldn't make sense of any of my google results from googling the errors. Can anyone point me in the right direction?
You cannot bind temporaries to non-const references.
iterator(iterator const& rhs) : data(rhs.data) {}
iterator(std::list<Piece>::iterator rhs) : data(rhs) {}
Note that iterators are conventially passed by value
Live On Coliru
#include <iterator>
#include <list>
#include <string>
#include <iostream>
struct Piece {
std::string name;
};
class PieceList
{
public:
PieceList(){}
PieceList(PieceList const& rhs){pieces = rhs.pieces;}
PieceList(std::list<Piece> const& rhs){pieces = rhs;}
friend std::ifstream& operator>>(std::ifstream&,PieceList&);
friend std::istream& operator>>(std::istream&,PieceList&);
class iterator
{
public:
friend class PieceList;
iterator(){}
iterator(iterator const& rhs) : data(rhs.data) {}
iterator(std::list<Piece>::iterator rhs) : data(rhs) {}
Piece operator*(){return *data;}
iterator& operator=(iterator& rhs){data=rhs.data;return *this;}
iterator& operator=(std::list<Piece>::iterator& rhs){data = rhs;return *this;}
bool operator==(iterator& rhs){return data==rhs.data;}
bool operator==(const iterator& rhs) const{return data==rhs.data;}
bool operator!=(iterator rhs){return data != rhs.data;}
iterator& operator++(){++data;return *this;}
iterator& operator--(){--data;return *this;}
private:
std::list<Piece>::iterator data;
};
iterator first(){iterator i;i.data=pieces.begin();return i;}
iterator last(){iterator i;i.data=pieces.end();return i;}
private:
std::list<Piece> pieces;
};
int main() {
PieceList pl { {
{ "aap" },
{ "noot" },
{ "mies" },
} };
for(auto it=pl.first(); it!=pl.last(); ++it) {
std::cout << (*it).name << "\n";
}
}
Prints
aap
noot
mies
You had a similar issue with the constructors of PieceList. Your iterator class is missing operator-> too. I'll leave that as an ExerciseForTheReader™

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