Hello.

I'm writing a manager class that should handle a vast and expandable group of classes. The manager class uses a hash_map to store all these etherogenous objects. The objects are all derivations of a base class Object, and of different "interface" classes which are used to define required functions. An example:

class Object{ ... };

class IUpdatable
{
	...
	public:
		virtual void Update()=0;
	...
};

So I could have classes that derive from class Object and from class IUpdatable, but that override the Update function in very different ways - or that do not even derive from IUpdatable (meaning that particular type of object requires no update at all after creation).

Now, I can't change this design. So, first I thought to just fill the hash map with pointers to Object, and (continuing with the example above) within the manager Update method, let the polymorphism kick in once I call the Update function of the updatable stored objects, like this:

void Update()
{
	// SHM is the hash map type, s is the hash map instance
	for (SHM::iterator i=s.begin(); i != s.end(); ++i)
	{
		i->second->Update();
	}
}

But obviously I can't do that, since
1. I do not know if the stored object derives from IUpdatable too.
2. Update is not a member of Object (and it makes no sense to have Update defined in Object).

I was thinking that I could just use typeid and confront the type info with all the possible types that derive from that "interface" class, but that's ugly programming imho. Maybe it's possible to check if a class implements a function (and in that case I'd automatically be allowed to cast the object to the IUpdatable type and use polymorphism).

So my question is, is there an elegant way to solve this situation?

Edited 6 Years Ago by CollDet: n/a

You ought to know at compile time if a class is updatable or not, because they will derive from the IUpdatable. So just add a field in Object class, isUpdatable, and set it appropriately for classes that derive from IUpdatable and classes that don't.

I would actually unify the two base classes. Instead of implementing the Update() as a pure virtual function, make it a callable function that is essentially a no-op: virtual void Update(){} . Then, all classes that need to be updated will implement their own Update() function. Now, all of your objects should be able to call the Update() method, though only the ones that actually need to be updated will actually do anything.

Well 1st of all thanks for taking the time to help me out.

To tell the truth I had already considered both solutions (the 1st one is an option if everything else fails, the 2nd I can't apply because I can't merge those classes), and then I felt very intelligent when I came up with this:

for (SCENEHASHMAP::iterator i=scene.begin(); i != scene.end(); ++i)
{
	dynamic_cast<IUpdatable*>(i->second)->Update();
}

Which, as far as I understand, should work nicely, casting the object to the IUpdatable type if possible, or NULLifying it (thus making the Update call ineffective)...

All of this, in the magical world where I can code perfectly.

Instead it fails to cast the objects at runtime - even if I feed objects that are indeed IUpdatable-derived to the manager.

RTTI is enabled in the project properties.

Am I doing something wrong?

This is not correct ... So if the pointer returned cannot be cast to IUpdatable*, it Nullifies the pointer and then you try to dereference a null pointer? Undefined behaviour ?

You could break that into 2 lines, cast and check if pointer is null or not and then proceed. Even then for dynamic_cast to work, IUpdatable should actuallt be pointing to that child class type.

Edited 6 Years Ago by Agni: n/a

This article has been dead for over six months. Start a new discussion instead.