What you are describing is exactly what inheritance is for.
If you want to make a global list, the parent class could have a static list member:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
// parent.h
class Parent
{
public:
Parent(); // default ctor (adds this object to the list)
virtual ~Parent(); // dtor (removes the object from the list)
// function called to update all "registered" objects
static void UpdateAll();
protected:
// the pure virtual "Update" function to be implemented by
// all derived classes
virtual void Update() = 0;
private:
// the list of "registered" objects
static std::list<Parent*> theList;
};
// parent.cpp
std::list<Parent*> Parent::theList; // instantiate the static list
// default ctor
Parent::Parent()
{
// register this object
theList.push_back(this);
}
// dtor
Parent::~Parent()
{
// remove from list
theList.remove(this);
}
// UpdateAll
void Parent::UpdateAll()
{
std::list<Parent*>::iterator i;
for(i = theList.begin(); i != theList.end(); ++i) // update each object in the list
i->Update();
}
|
Derived classes simply need to supply the 'Update' function, and have 'Parent' as one of their parents, and they're automatically registered and get updated by the UpdateAll call.
EDIT:
A word of warning with this approach. Do not have any global or static instances of Parent or any derived classes, as this would trigger the static initialization order fiasco. If you need global objects there is a work-around.
EDIT2:
You'd also need to register the objects in the copy ctor if object copying is allowed.
EDIT3:
To explain the "is a" bit...
A better name for "Parent" would probably be "UpdatingObject" or something similar. Since that is effectively what the class represents: an object that updates.
If you have a class Foo that's derived... then Foo "is an" Updating Object because it updates. Anything that you can do with an UpdatingObject you can do with a Foo, because a Foo
is an UpdatingObject.