Once again I find myself failing at some really simple task in C++. Sometimes I wish I could de-learn all I know from OO in java, since my problems usually start by thinking like Java.
Anyways, I have a std::list<BaseObject*> that I want to sort. Let’s say that BaseObject is:
class BaseObject {
protected:
int id;
public:
BaseObject(int i) : id(i) {};
virtual ~BaseObject() {};
};
I can sort the list of pointer to BaseObject with a comparator struct:
struct Comparator {
bool operator()(const BaseObject* o1, const BaseObject* o2) const {
return o1->id < o2->id;
}
};
And it would look like this:
std::list<BaseObject*> mylist;
mylist.push_back(new BaseObject(1));
mylist.push_back(new BaseObject(2));
// ...
mylist.sort(Comparator());
// intentionally omitted deletes and exception handling
Until here, everything is a-ok. However, I introduced some derived classes:
class Child : public BaseObject {
protected:
int var;
public:
Child(int id1, int n) : BaseObject(id1), var(n) {};
virtual ~Child() {};
};
class GrandChild : public Child {
public:
GrandChild(int id1, int n) : Child(id1,n) {};
virtual ~GrandChild() {};
};
So now I would like to sort following the following rules:
- For any
ChildobjectcandBaseObjectb,b<c - To compare
BaseObjectobjects, use itsids, as before. - To compare
Childobjects, compare itsvars. If they are equal, fallback to rule 2. GrandChildobjects should fallback to theChildbehavior (rule 3).
I initially thought that I could probably do some casts in Comparator. However, this casts away constness. Then I thought that probably I could compare typeids, but then everything looked messy and it is not even correct.
How could I implement this sort, still using list<BaseObject*>::sort ?
Thank you
You are looking at doing double dispatch – that is calling a virtual function depending on the types of two objects rather than one. Take a look at this wikipedia article for a heads-up http://en.wikipedia.org/wiki/Double_dispatch. I have to say that whenever I find myself in this situation, I try to change direction 🙂
And can I make a couple of observations about your code. There is nothing precisely wrong with it but:
in C++, the std::list is the container of last resort – you should normally default to using a std:;vector, unless you specifically need a feature that only list provides:
protected data is always a bad idea