Abstract Interfaces

Published June 05, 2007
Advertisement

Abstract Interfaces


Lately I've been brushing up on some of the more advanced c++ topics. The book I've found really helpful in this is C++ for Game Programmers. Something that I've picked up from this book and really want to use in my current projects are Abstract Interfaces. Here's a quick example from the book that I've been playing about with to understand the idea of interfaces a little better.


// Abstract Interface that provides a rendering interface to// derived classesclass IRenderable{public:	virtual void Render(void) = 0;};// Abstract Interface that provides a simple physics interface to// derived classesclass IPhysical{public:	virtual void UpdatePhysics(void) = 0;};// Game Entity base classclass Entity{public:	virtual void Update(void) = 0;	QUERY_INTERFACE_BEGIN	QUERY_INTERFACE_END};// A Tree Game Entity (not to be mistaken for a tree data structure) this is one of// those green things out the window. Has rendering capabilitiesclass TreeEntity : public Entity, IRenderable{public:	void Render(void);	void Update(void);	QUERY_INTERFACE_BEGIN		QUERY_INTERFACE_ADD(IRENDERABLE, IRenderable)	QUERY_INTERFACE_END};// A Player Game Entity has both physics and rendering capabilitiesclass PlayerEntity : public Entity, IRenderable, IPhysical{public:	void Update(void);	void Render(void);	void UpdatePhysics(void);	QUERY_INTERFACE_BEGIN		QUERY_INTERFACE_ADD(IRENDERABLE, IRenderable)		QUERY_INTERFACE_ADD(IPHYSICAL, IPhysical)	QUERY_INTERFACE_END};


Using this setup I can store all of my game objects in a single array / vector / list. Iterate through them and at runtime decide whether or not I need to call Render() and / or UpdatePhysics(). Pretty neat, considering before this I was either using an isVisible boolean flag or storing visible objects in a seperate container. Here's a sample of these classes being used:

int main(void){	std::list entityList;	entityList.push_back(new TreeEntity());	entityList.push_back(new PlayerEntity());	entityList.push_back(new TreeEntity());	entityList.push_back(new PlayerEntity());	std::list::iterator itr;	for(itr = entityList.begin(); itr != entityList.end(); itr++)	{		void* pInterface;		(*itr)->Update();		pInterface = (*itr)->QueryInterface(IPHYSICAL);		if(pInterface != NULL)		{			IPhysical* pInst;			pInst = static_cast(pInterface);			pInst->UpdatePhysics();		}		pInterface = (*itr)->QueryInterface(IRENDERABLE);		if(pInterface != NULL)		{			IRenderable* pInst;			pInst = static_cast(pInterface);			pInst->Render();		}	}	system("pause");	return 0;}


-- On a side note, I had to make a change to the code presented in the book in order to get it to work. I'm pretty sure it was correct but if someone could double check this for me it would be great. In the book, the QueryInterface() method is implemented just in the base class and isn't virtual, the only way I could get it to work was as follows:

#define QUERY_INTERFACE_BEGIN     virtual void * QueryInterface(Interface interface) {#define QUERY_INTERFACE_ADD(q, p)     if(interface == q){p* inst = static_cast(this); return (void *)(inst);}#define QUERY_INTERFACE_END     return NULL;}
0 likes 3 comments

Comments

Sir Sapo
I bought that book on a whim one day, and it was probably the best thing that has ever happened to me programming wise.
June 05, 2007 10:16 PM
Moomin
Why do you choose to use interface query functions, can't you just use dynamic_cast and check for null?
June 07, 2007 07:55 AM
FunLogic
By using dynamic_cast, I'm assuming you mean as opposed to using static_cast within the query function and when accessing the interface within my "game loop".

Performance for one thing, as static_cast performs no run-time type checks, it's got much less of a performance overhead than dynamic_cast. Sure dynamic_cast is a lot safer, and static_cast is really only advised for numeric data type conversions and when your absolutely sure that casting will work. But if this system was used to manage a game with hundreds of objects of a class derived from numerous interfaces - dynamic_cast would kill performance.
June 07, 2007 10:33 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement