A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | 0-9
Singleton - A class of which only one instance can exist at a given time. This instance can be accessed from anywhere in the program without passing a reference to it around. A useful design pattern, but apply with care.
Table of contents
A general approach
Forum Answer
Taken from here here:
Mdobele:Singleton Classes rock. Simply think of it as a way of ensuring that the class you are calling is created only once. That means it can be called from anywhere ( by including header of course ) and you know that your calling the 1 static instance and not creating another instance.
I use them mostly for my main application and then for every single "manager" class that I use.
Here is an example of a Menu manager
// Class Declaration class MenuManager { public : // Constructor MenuManager(); // Destructor ~MenuManager(); // SingleTon Instance // Singleton Instance of our Menu manager static MenuManager &Instance(); // Create Main Menu void CreateMainMenu(); private: InheritedBase *m_BaseMenu; MainMenu * m_MainMenu; };
//SingleTon Instance MenuManager &MenuManager::Instance() { static MenuManager instance; return instance; } // Create MainMenu void MenuManager::CreateMainMenu() { m_MainMenu = new MainMenu(); m_MainMenu->CreateMainMenu(); }
So in any other file i simply include
#include MenuManager.h
and I gain acess to it Knowing that its the one and only and not another instance.
MenuManager::Instance().CreateMainMenu();
Hope that clears it up a bit.
bal:
IIRC, singletons are a design pattern (a way of creating classes that fits in most projects). There are a lot of different implementations but the point is always the same: having ONLY ONE instance of a class.
Ogre's approach
Description
Ogre's implementation differs in a couple of points from the approach described above.
- Ogre::Singleton is a template, meaning you must instantiate it with the type, that you want to have as a Singleton. This allows us to handle all Singletons with the same code, which makes the code a bit more maintainable.
- Ogre::Singleton must be constructed explicitly. You must call the constructor of your Singleton class, before you can obtain a reference to the instance. The implementation described above creates the singleton on the fly when the instance is obtained for the first time. The advantage of Ogre's implementation is that you can instantiate it with arbitrary parameters.
The Source can be found here.
How to use it
NOTE: In Ogre 1.7, the static member msSingleton we are referring to below will actually be called ms_Singleton. The code below assumes you use Ogre 1.8 or later.
Making a class a singleton
Pretend we want to convert the class MyManager to a Singleton.
class MyManager { public: MyManager(); void doSomething(); };
So we need to extend and instantiate the Ogre::Singleton template and override the singleton access methods. Our header file will look like this:
#include <OgreSingleton.h> class MyManager : public Ogre::Singleton<MyManager> { public: MyManager(); void doSomething(); static MyManager& getSingleton(void); static MyManager* getSingletonPtr(void); };
You don't have to override getSingleton()
and getSingletonPtr()
if your Singleton is not used outside of your EXE/DLL, but else you have to.
The source file would now look like this:
#include "MyManager.h" template<> MyManager* Ogre::Singleton<MyManager>::msSingleton = 0; MyManager* MyManager::getSingletonPtr(void) { return msSingleton; } MyManager& MyManager::getSingleton(void) { assert( msSingleton ); return ( *msSingleton ); } // The rest of your implementation is following. ...
Making a class (in another namespace) a singleton
If you want to make a class from a specific namespace a singleton, you cannot use the previous method.
Due to C++ specification (C++ Standard 14.7.3/2) you cannot specialize a template (like Ogre::Singleton<T>) in other namespace than its declaration's one.
Here is a complement to the previous technique.
There is two case where you need another namespace :
- Your class is a part of an application directly using Ogre3D
- Your class is a part of a library (DLL) directly using Ogre3D but, like all DLLs, attends to be used by another program.
The two cases are pretty close.
The fellowing code is needed only for the case 2. A good practice when developping a DLL is to define a macro for export/import depending on the building situation (building the lib itself => export ; build an app with the lib => import).
// File MyLibPrereq.h # if defined(MYLIB_NONCLIENT_BUILD) // Export definition # define _MYLIBExport __declspec( dllexport ) # else // Import definition # define _MYLIBExport __declspec( dllimport ) # endif
The header file for MyManager in case 1 :
#include "MyLibPrereq.h" #include <OgreSingleton.h> namespace MyLib { class MyManager; } template class _OgreExport Ogre::Singleton<MyLib::MyManager>; // export of explicit instantiation namespace MyLib { class MyManager : public Ogre::Singleton<MyManager> { public: MyManager(); void doSomething(); static MyManager& getSingleton(void); static MyManager* getSingletonPtr(void); }; }
Now the header for MyManager in case 2. The difference reside in the export directive, here we use our own directive :
#include "MyLibPrereq.h" #include <OgreSingleton.h> namespace MyLib { class MyManager; } template class _MYLIBExport Ogre::Singleton<MyLib::MyManager>; // export of explicit instantiation namespace MyLib { class MyManager : public Ogre::Singleton<MyManager> { public: MyManager(); void doSomething(); static MyManager& getSingleton(void); static MyManager* getSingletonPtr(void); }; }
Then the source for case 2:
#include "MyManager.h" // Template specialization template<> _MYLIBExport MyLib::MyManager* Ogre::Singleton<MyLib::MyManager>::msSingleton = 0; namespace MyLib { MyManager* MyManager::getSingletonPtr(void) { return msSingleton; } MyManager& MyManager::getSingleton(void) { assert( msSingleton ); return ( *msSingleton ); } // The rest of your implementation is following. ... }
For case 1 just remove _MYLIBExport
in the template specialization.
Using a singleton
// Creating the manager. This may only be called once! new MyManager(); // Obtaining a reference to the manager instance MyManager& mgr = MyManager::getSingleton(); // Obtaining a pointer to the manager instance MyManager* pMgr = MyManager::getSingletonPtr();
Note: You may call the Singleton constructor only once. Calling it more often will result in a runtime exception.
There is another semantical difference between getSingleton()
and getSingletonPtr()
: If the constructor is not called beforehand getSingletonPtr()
will return a NULL-Pointer and getSingleton()
will throw a runtime exception. So it is probably better to use getSingleton()
most of the time, even though it is slightly slower. But you get a clearer response when you set something up wrongly.
Some Links:
Ogre's Singleton Method from 'Game Programming Gems' by Scott Bilas
A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | 0-9
Alias: Singleton