C++ container - set and object - c++

I have following class.
class Student {
//Parameterized constructor.
private:
int rollNo;
char* name;
float marks;
}
I have a set<Student> students. When I insert a student object in set, how can I sepcify that two objects are same. E.g. I am considering two objects same if their rollNo is same so Student s1(10,"ABC",35) and Student s2(10,"XYZ",67) both are same. So when I say students.insert(s1) and students.insert(s2), set will have only one object i.e. s1.

I've never done this in c++ but a quick look at http://www.cplusplus.com/reference/set/set/set/
explains it nicely.
Basically when you instantiate the set you need to give it a comparison object which " returns true if the first argument goes before the second argument"
for ints it could be
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
in your case that would be more like
struct StudentCompare{
bool operator() (const Student& lsh, const Student& rhs) const
{
return lhs.rollNo < rhs.rollNo; //or however they need to be compared
}
};
and then you can instantiate it like
std::set<int,StudentCompare> mySet;
This wont work as is for your code as rollNo is private. I recommend that you read the page i linked to above to better understand is going on.

You need to declare and define friend operator> for class Student
Example code
class Student {
/* everything you already have */
public:
friend bool operator<(const Student& lhs, const Student& rhs);
};
bool operator<(const Student& lhs, const Student& rhs) {
return lhs.rollNo < rhs.rollNo;
}
Solution provided thermite does not work because compare function doesn't have access to private members of class Student. To solve this problem, you can declare operator< as friend. A friend function (or class) can access the private and protected members of the class in which it is declared as a friend.

The way I do this is just define the less then operator - if neither of two elements is less then the other then they are effectively equal/equivalent to each other - the "original" thread linked by Daniel shows this nicely.

Related

Sort vector of objects by value of member [duplicate]

For an assignment students have to make a Card struct that keeps the Suit, Rank and Bitmap of a Card. This struct needs an overloaded "<" operator to compare whether the lhs Card's Rank is smaller than the rhs Card and return the bool. So far this is my Card.h file:
#pragma once
#include "GameEngine.h"
struct Card
{
public:
//Constructor and Destructor
Card();
virtual ~Card();
//Methods
bool operator< (const Card& lhs, const Card& rhs)
{
return (lhs.m_Rank < rhs.m_Rank);
}
//Enumerations
enum class Suit
{
Diamonds,
Clubs,
Hearts,
Spades,
};
enum class Rank
{
RankAce,
RankTwo,
RankThree,
RankFour,
RankFive,
RankSix,
RankSeven,
RankEight,
RankNine,
RankTen,
RankJack,
RankQueen,
RankKing,
};
private:
//Datamembers
Bitmap *m_BmpPtr;
Rank m_Rank;
Suit m_Suit;
};
However the operator< overload claims that it has too many parameters. Isn't this the right way to make sure both lhs and rhs can be compared in one overload? It's not like I have to split it up right?
Many thanks in advance.
The compiler think this is a member function, but member function operators cannot have more than one argument. The first argument is implicitly *this while the second is the one you supply.
You can make this a member function by stripping the first argument and using *this in place of lhs. Otherwise, you can use an idiomatic solution and make it a friend:
friend bool operator< (const Card& lhs, const Card& rhs)
{
return lhs.m_Rank < rhs.m_Rank;
}
You have declared bool operator< as a member function. Member functions have an implicit first parameter for this, so your operator really expects three parameters. You can solve this by using a non-member (friend in your case - remember that friend functions are non-member functions):
friend
bool operator< (const Card& lhs, const Card& rhs)
{
return (lhs.m_Rank < rhs.m_Rank);
}
or using a member with a single rhs parameter:
bool operator< (const Card& rhs) const
{
return (m_Rank < rhs.m_Rank);
}

printing with polymorphism and inheritance

I have a problem with polymorphism and inheritance.
The parent class is:
class IIR_filter {
private:
double* a_;
double* b_;
unsigned int order_;
void reverseArray(double* source, double* destination, unsigned int size);
public:
IIR_filter();
IIR_filter(double* a, double* b, unsigned int order); //c'tor
IIR_filter(const IIR_filter& filter); //copy c'tor
virtual ~IIR_filter(); //d'tor
virtual void filter(double* inputX, double* outputY, unsigned int size);
virtual void zeroPhaseFilter(double* inputX, double* outputY, unsigned int size);
friend ostream& operator<<(ostream& lhs, const IIR_filter& rhs);
protected:
double filterSample(unsigned int indexY, double* outputY,double newSample, Queue<double>& filter);
double getElementA(unsigned int index) const;
double getElementB(unsigned int index) const;
unsigned int getOrder() const;
virtual void print(ostream& lhs, const IIR_filter* rhs)const;
};
and the cpp relevant functions are:
ostream& operator<<(ostream& lhs, const IIR_filter& rhs){
std::cout << "IIR filter: " << std::endl;
rhs.print(lhs, &rhs);
return lhs;
}
and the derived class is:
class FIR_filter : public IIR_filter {
public:
FIR_filter(double* b, unsigned int order); //c'tor
friend ostream& operator<<(ostream& lhs, FIR_filter* rhs);
};
And the cpp function is:
ostream& operator<<(ostream& lhs, FIR_filter* rhs){
lhs << "FIR filter: \n";
rhs->print(lhs, rhs);
return lhs;
}
And of course there is the print function in the IIR_filter class, but it's too long and irrelevant for my opinion.
The problem is:
When I call the printing function (operator<<) from an object of the derived class, the print is done from the parent class, so instead of the header "FIR filter" i get the header "IIR filter".
I have tried many ways but have no success.
Please help.
Thank, Ran.
You should move the writing of a header into a stream inside the virtual print function, and create a suitable override in the derived class. You might also want to refactor the code to have a virtual print_header function called inside a non-virtual print, since you're currently not overriding it in the derived class.
By the way, you have inconsistency - one operator<< is accepting a reference to a const object, and the other is accepting a pointer. But even if you unified your convention, the operator<< is still not virtual, so it cannot determine in runtime if the reference (or pointer) to the base type indeed points to a derived object. It means, that in current state, it will (and should) always print the "IIR filter" header.
You can't derive friend ship.
See this question for more details:
friend class with inheritance
Also, like that was mentioned before, You should have one overloaded operator<< in base class which just returns only output of print function. Than in print implementations You can do all printing and other stuff for all Your classes.

overloading class operators for pointers

Is it even possible?
So I have
class Organism{
// ....
public:
virtual std::string type(){
return "Organism"
}
// ....
}
I also have derived clases ant, beetle, witch return "Ant" / "Beetle"
I have one more class World where things happen.
In World class there are Organism* world[20][20];
I want to create operator that comperas word[x][y] to world[x1][y1]
I managed to create operator:
friend bool operator== (const Organism &lhs, const Organism &rhs){
return lhs.type() == rhs.type();
}
but what I want is something like this:
friend bool operator== (const Organism* lhs, const Organism* rhs){
return lhs->type() == rhs->type();
}
but it doesnt allow it VS13 says "Error: nonmember operator requires a parameter with class or enum type".
How to achieve this?
ps. I can't even write const after closing ).

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
// ^^^^^

Can ostream overloading be a function member?

I have a class Counter and I want to overload operator << to output the data member of Counter. I tried to make the ostream overloading a member function:
Counter{
public:
std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
int count_;
};
std::ostream& Counter::operator<<(std::ostream& outStream, const Counter& c){
outStream << c.count_;
return outStream;
}
But the g++ compiler always outputs the same error:
‘std::ostream& Counter::operator<<(std::ostream&, const Counter&)’ must take exactly one argument
However, if I changed the overloading function to be a friend of the class, it worked all well, like this:
Counter{
public:
friend std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
int count_;
};
std::ostream& operator<<(std::ostream& outStream, const Counter& c){
outStream << c.count_;
return outStream;
}
Does this mean that the the stream operator overloading cannot be a member function of a class?
Add a public query method that returns the value of count_, then it does not have to be a friend:
Counter{
public:
int count() const { return count_; }
private:
int count_;
};
std::ostream& operator<<(std::ostream& outStream, const Counter& c){
outStream << c.count();
return outStream;
}
If you put the ostream operator in the class itself then it will not work the way you expect it to. It would be a member function meaning to invoke it one would have to do this: c.operator<<("output") which is obviously not what you mean to do. For it to work as you expect an ostream operator it must be outside the class. You can do this by making it a friend or just put it outside of the class and use getters (accessors) to output the data.
It doesn't have to be a friend, but it can't be a member. Member operators only work when they are inside the class which corresponds to the left-hand operand.
Unfortunately the useful overloads for the streaming output operators ( << ) cannot be class members, because the ostream& must be on the left in use and declaration. They do not need to be friends of the class you wish to stream unless they need access to protected or private members. This means that if you can implement a streaming operator using just public functions such as observers/accessors without declaring it a friend.
In your first Counter class you are declaring a member function of the class that does not seem valid. In the second example of the Counter class you are stating that your operator overload for << , which seems valid, has access to the private members. In the second example the function must still be declared outside the class.
Wikipedia Operators in C and C++ has a good list of possible operator overloads, including the in class << overloads even though they are not very useful. The in class overloads must be called backwards CounterInstance << cout; which is counterintuitive.