I want to explain you how that works in this post.
As you might know, I work with a component based object model in my engine (see here).
In this kind of object model, you sometimes need to modify the component of certain objects after you added them.
To do that I implement a getComponent() function, which - in the past - returned a object of the type of the component interface (called IComponent). Type conversions needed to be made afterwards to work with the desired implementation. That used to look like this:
GameObject gameobject; RenderableComponent *renderableComponent = new RenderableComponent("graphic.png"); gameobject.addComponent(renderableComponent);
//Somewhere else in the code in another function.
IComponent *component = gameobject.getComponent("RenderableComponent"); RenderableComponent *renderableComponent = static_cast<RenderableComponent*>(component);
//.. do stuff with renderablecomponent.
I found that code pretty ugly and unnecessary complicated, so I thought of another idea to do that user friendlier. The first step I did was to change the getComponent() function to a template function.
The function looked like this:
IComponent *GameObject::getComponent(const String &componentName){
for(std::list<IComponent*>::iterator i = this->m_components.begin();i != this->m_components.end();i++){
if((*i)->getType() == componentName){
return (*i);
}
}
return NULL;
}
With template support it now looks like this:
template<class T>
T *getComponent(const String &componentName){
for(std::list<IComponent*>::iterator i = m_components.begin();i != m_components.end();i++){
if((*i)->getType() == componentName){
return static_cast<T*>((*i));
}
}
return NULL;
}
(Hint: If you don't know nothing about template functions, check here)As you can see, the user determines the return type via the template type ( So there's no ugly conversion needed afterwards.)
The result is (in my opinion) much nicer source code.
The following is the above example reused with the new getComponent() template function:
I don't know what about you, but I find it much nicer ;) .GameObject gameobject; RenderableComponent *renderableComponent = new RenderableComponent("graphic.png"); gameobject.addComponent(renderableComponent);
//Somewhere else in the code in another function. //IComponent *component = gameobject.getComponent("RenderableComponent"); //RenderableComponent *renderableComponent = static_cast<RenderableComponent*>(component);
RenderableComponent *renderableComponent = gameobject.getComponent<RenderableComponent>("RenderableComponent");
//.. do stuff with renderablecomponent.
Compared with a macro like:
#define GET_COMPONENT(type)(getComponent<type>(#type))
The example could even get more improved to look like this:
GameObject gameobject; RenderableComponent *renderableComponent = new RenderableComponent("graphic.png"); gameobject.addComponent(renderableComponent);
//Somewhere else in the code in another function. //IComponent *component = gameobject.getComponent("RenderableComponent"); //RenderableComponent *renderableComponent = static_cast<RenderableComponent*>(component);
RenderableComponent *renderableComponent = gameobject.GET_COMPONENT(RenderableComponent);
//.. do stuff with renderablecomponent.
No comments:
Post a Comment