Tuesday, July 18, 2006

A Single way

Many times a few years ago I wondered why anyone would want to use Singletons in programming projects, that is, untill I reached half way through my 2nd year in university when we did Java and proper Object Orientated programming. I wasn't too happy about Java in the beginning but as I progressed through the cource I found how easy it was to implement somthing in comparison to C++. Java had it all, C++ you had to write it all, he he!
Don't get me wrong, I still like C++ alot and Java isn't on my hated-programming-list anymore. LOL!

It was when I wrote a Java multiplayer game for a project that I realised how useful Singletons are. It helps you make classes independant and available to everything. This is essential for Manager classes. In Java, all you have to do is make a class with static variables and methods. Whoala, a singleton class! He he!
In C++ its exactly the same, only I stumbled upon a cool Singleton super-class that you can derive from to make your class a Singleton one. Then to make it auto memory managed, just make a static variable of itself somewhere in the class's cpp file.

This was found originally from Scott Bilas in his book Game Programming Gems, I just found it off an article at Gamedev.net:

This is the Singleton class:


template < class T >
class CSingleton
{
public:
CSingleton()
{
//Uses a cunning trick to get the singleton pointing to
//the start of the whole, rather than
//the start of the Singleton part of the object
int offset = (int)(T *)1 - (int)(CSingleton<T> *)(T *)1;
mPtr = (T *)((int)this + offset);
}

~CSingleton() { mPtr = NULL; }

static T & getSingleton() { return *mPtr; }
static T * getSingletonPtr() { return mPtr; }

private:
static T * mPtr;
};

template <class T> T * CSingleton::mPtr = NULL;


If you have a class CTextureManager, let it derive publicly from CSingleton and there you go. If you know Singletons, then you know that you can obtain that class instance by saying : CTextureManager::getSingletonPtr()->texture_man_function();
Just make a MACRO to shorten your function calls.
Then in your CTextureManager.cpp file (example), just add the following at the top or something:

static CTextureManager texture_manager;

Don't use texture_manager but the call above it. You might wonder, why do that while a global var will do? Well its cleaner, if you use MACROs and more structured. Now you only need to (#include "CTextureManager.h") if you need the texture manager. I am currently implementing it in my project's manager classes. I think it works much better than passing variables to and throu or using global variables.
And it's good for team-based projects. You know what I mean? Well, it is one of those "Use it if you want to" things.

No comments: