how to store polymorphic object in set - c++

how to define overloaded comparison operator or comparison functor, so that i can create the set of class A. i have a class Base which have int member variable _state and a derived class A.
#include <vector>
#include <set>
class Base{
int _state;
protected:
virtual void fun() = 0;
public:
bool operator < (const Base & t)
{
return (this->_state < t._state);
}
Base (int s): _state(s){}
virtual ~Base() = default;
};
class A: public Base{
public:
A(int s): Base(s){}
void fun() override{}
};
int main()
{
A a(5);
std::set<A> s;
s.insert(a);
return 0;
}

how to define overloaded comparison operator or comparison functor, so that i can create the set of class A.
Set elements are const, and therefore such comparison operator must accept a const argument.
Your overloaded comparison operator does not accept a const left hand argument because you did not const qualify it. Solution: Add const qualifier:
bool operator < (const Base & t) const
I recommend not defining comparison operators as non-static member functions because they lack the symmetry of free functions. It would probably have been much less likely for you to have made the mistake of writing bool operator < (Base & l, const Base & r) because the symmetry makes the mistake obvious.

Related

Implementing pure virtual functions (operator overrides)

I am trying to implement operator overrides (for use in a set). I have a base class and a derived class:
// Base.h
class Base {
public:
virtual bool operator < (const Base&) const = 0;
}
// Derived.h
class Derived : Base {
public:
virtual bool operator < (const Derived&) const;
private:
int num;
}
// Derived.cpp
bool Derived::operator < (const Derived& obj) const {
return num < obj.num;
}
My initial approach threw an error: 'Base': cannot instantiate abstract class when Derived is being used in another file. Is there a way to write a pure virtual function in Base such that all its Derived classes are required to implement it?
This is because there seems to be some redundancy if the same function declaration had to be made in every Derived class (apart from its parameter).

Virtual comparison operator

Is there any reason to make the op== in a C++ base class non-virtual, i.e., is there any downside to this implementation:
class A {
public:
virtual bool operator== (const A& rhs) { ... }
};
class B : public A {
public:
bool operator== (const A& rhs) override { /* cast rhs to const B& */ {}
};
In my book they recommend to make the op== non-virtual and let it call a protected virtual member function which performs the polymorphism instead. It doesn't say anything about why they don't use the op== directly like I do in my example above. Is there a good reason I'm overlooking?

Friend functions and derived classes

I'm trying to derive a class from a Base that has a friend function defined. I want to create a friend function for my derived class that makes use of the Base's friend function, but preserves the type of my Derived class:
#include<algorithm>
class Base
{
public:
Base(int i, int j, int k)
{
vect[0] = i;
vect[1] = j;
vect[2] = k;
}
~Base();
friend Base myMin (const Base& argA,
const Base& argB);
protected:
// Member data
int vect[3];
};
class Derived : public Base
{
public:
Derived(int i, int j, int k)
:
Base(i,j,k)
{
}
~Derived();
friend Derived doSomething(const Derived& argA,
const Derived& argB);
};
Base
myMin (const Base& argA,
const Base& argB)
{
int i = std::min(argA.vect[0], argB.vect[0]);
int j = std::min(argA.vect[1], argB.vect[1]);
int k = std::min(argA.vect[2], argB.vect[2]);
return Base(i,j,k);
}
Derived doSomething(const Derived& argA,
const Derived& argB)
{
// Does other stuff too...
return myMin(argA, argB);
}
int main(int argc, char *argv[])
{
Derived testA(2,4,6);
Derived testB(3,3,7);
doSomething(testA,testB);
return 0;
}
I understand why this doesn't work (doSomething is given a Base to return, but is told to return Derived), and that this probably isn't very good C++ form. My Base class has a ton of friend functions similar to this, is there a way to make use of the friend functions with my Derived class without having to modify them?
Thank you
Edited: The error, for reference, is:
base.H: In function ‘Derived doSomething(const Derived&, const Derived&)’:
base.H:50:26: error: could not convert ‘myMin(const Base&, const Base&)((* &(& argB)->Derived::<anonymous>))’ from ‘Base’ to ‘Derived’
return myMin(argA, argB);
The most obvious way would be to change doSomething() to
Derived doSomething(const Derived& argA,
const Derived& argB)
{
Base temp(myMin(argA, argB));
Derived retval(temp.vect[0], temp.vect[1], temp.vect[2]);
return retval;
}
You'll probably also have to declare doSomething() to be a friend of Base as well.
Without knowing more about what you are REALLY trying to do, hard to advise further. The fact you need to do this at all is an example of a "code smell" - a positive sign that your design is flawed and, as your code keeps growing, you will keep needing to do workarounds like this. That gradually makes it harder and harder to change the code - each time you change one part, something else has to be worked around.

Swap-Idiom of abstract class with private data members

Assume we have this two classes, with implemented swap-idioms. The copy constructor and assignment operator of the base class are deleted, as it makes no sense. However the swap-method is implemented, as it holds a member.
namespace std
{
template<>
void swap<Base>(Base& a, Base& b)
{
a.swap(b);
}
template<>
void swap<Derived>(Derived& a, Derived& b)
{
a.swap(b);
}
}
class Base
{
public:
Base(int ID) : ID_(ID) {}
virtual std::string getString()=0;
Base(const Base&)=delete;
operator=(const Base&)=delete;
void swap(Base& rhs)
{
std:swap(ID_, rhs.ID_);
}
private:
int ID_;
}
class Derived : public Base
{
public:
Derived(int ID, bool Value) : Base(ID), Value_(Value) {}
virtual ~Derived() {}
Derived(Derived& rhs)
{
std::swap(*this, rhs);
}
virtual std::string getString() {return Value_ ? "True" : "False"}
void swap(Derived& lhs, Derived& rhs)
{
std::swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs);
std::swap(lhs.Value_, rhs.Value_);
}
private:
bool Value_;
}
As seen in many examples, this would be the standard way to do it I suppose.
However, I see a problem with the public Base::swap, as it should not be possible to swap only the abstract base-class!
Wouldn't it be better to remove the template for the Base class and make the Base::swap Method protected:
class Base
{
...
protected:
void swap(Base& rhs, Base &lhs);
}
class Derived : public Base
{
...
public:
void swap(Derived& lhs, Derived& rhs)
{
Base::swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs);
std::swap(lhs.Value_, rhs.Value_);
}
}
Assuming, there is another class derived from base, with the first implementation it would be possible to swap the ID, however the data members of the derived objects would stay the same.
So, am I right thinking that swapping of a abstract class should not be possible from outside?
The copy constructor and assignment operator of the base class are deleted, as it makes no sense.
Actually, this is terrible. Now you made Derived uncopyable! Why? There is no reason to add this restriction. The default copy constructor and assignment operator of Base are perfectly reasonable in the context of copying the most-base class of the hierarchy.
Once you undo that, there's no need to do anything else as std::swap(derived1, derived2) would already do the right thing. The default move construction/operation is correct. It's always good to let the compiler do things for you.
But if you want to override swap anyway, the correct way to do that would be as a non-member friend:
class Base {
...
friend void swap(Base& lhs, Base& rhs) {
using std::swap;
swap(lhs.ID_, rhs.ID_);
}
};
class Derived : public Base {
...
friend void swap(Derived& lhs, Derived& rhs) {
using std::swap;
swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs));
swap(lhs.Value_, rhs.Value_);
}
};
Also, your Derived copy constructor makes no sense. Remove it as per the first paragraph of my answer.

Overloading binary operator> in a derived class in c++

I have searched far and wide for a specific answer to this question, and cannot find it. I am trying to create a base class with a virtual operator> that I can override in the derived class. Currently I'm having problems because declaring the function only requires one input variable (as in "bool operator> (Derived & a)" but attempting to define it in a cpp file tells me that it requires two inputs (as in "bool operator> (Derived & a, Derived & b))
I've tried defining the operator inline, but then I get errors where it thinks the derived class is still abstract because I'm passing in the derived type to the operator as shown above, instead of the base class. But if I pass the base class, then I cannot access the derived member variables I need to make the comparison.
I think I'm missing something simple here but I cannot seem to figure out what it is.
Hopefully you can help.
Thanks
For virtual calls to work from a reference/pointer of the base, you will need to use the base-type in the function, so for example
class Derived : public Base
{
....
bool operator>(Base &a)
{
Derived *pa = dynamic_cast<Derived *>(&a);
return this->something > pa->something; // Or whatever...
}
....
};
If you change the type, it becomes a different function, and when you use the base pointer or reference to refer to operator>, it will use the one in the base-class.
Why don't you leave operator>() non-virtual, und have it call a private virtual function?
Like so:
class Base {
public:
bool operator>(Base &a) {
return implementingFunction(a);
}
private:
virtual bool implementingFunction(Base &a) = 0;
};
#include <iostream>
using namespace std;
class base{
public :
virtual bool operator> (base& obj) { cout<<"b\n";return true;}
virtual ~base(){}
};
class derived: public base{
public:
virtual bool operator> (derived& obj) { cout<<"d\n";return true;}
~derived(){}
};
int main()
{
base *a=new derived(),b;
if(*a>b) { delete a; cout<<"Done!\n"; }
return 0;
}
Old question, but I've hardly seen a useful/correct answer here, so I would add my suggestion:
struct base
{
virtual ~base() = default;
virtual bool operator> (base const& obj) const = 0;
};
struct derived: public base
{
derived(int member) : member(member) {}
int member = 0;
virtual bool operator> (base const& obj) const
{
return member > static_cast<derived const&>(obj).member;
}
};
int main()
{
//in reality one would use a unique_ptr, of course
base* a = new derived(1);
base* b = new derived(0);
if(*a > *b)
{
//do something
}
return 0;
}
Caution: this works safely only if you're sure that the base const& parameter is really a derived const& (as e.g. in CRTP).
If not, you should use a dynamic_cast and add some error handling.