Singleton vs Global

Started by
9 comments, last by clabinsky 22 years, 3 months ago
Ok, so I have not used a Singleton yet and have thought, dreamed and hallucinated about the best of use for a Singleton class in my system. I have searched google, searched GD net, looked in Thinking C++ and Programming Gems and I do understand the theory but I am not sure about the implementation. Please give me your thoughts on each idea and if I am totally wrong in my reasoning. Instead of extern declarations of a global I can do as below. I a going to implement two Singletons for now. One is class that enumerates the card and sets the display. The other is a class with Primary surface and backbuffers. The Singletons are: CSingeltonDevice (CSingDevice.h) and CSingletonScreen (CSingScreen.h) In all subclasses that needs to reference the Singletons I need to: a) #include "CSingScreen.h" or/and #include "CSingDevice.h" //Declare the object as a member object such as: CSingletonDevice *CDevice; and/or CSingletonScreen *CScreen; //Even if the each Singleton is initiated in global scope //each class that calls them gets one and only one instance //of the object. This instance is unique in the system(?). //To use the Singleton I just: CScreen.GetPrimary(); //returns pointer to surface OR b) In the Singleton class I declare friend classes that can access the object and do not declare an object within the class - instead call to get the object when necessary. The reason that I am kind of not sure about this is that the encapsulation still suffers in the examples above. Each class that uses the Singletons is dependent on the Singleton itself but I guess this isn´t possible to avoid unless using templates where a subclass could be initiated with an arbitrary Singleton, ah well I don´t know. Your comments are highly appreciated since I am coding right now. //EDIT: I spell like a Swede 2EDIT: still unclear, hmm I am actually a Swede, living in paradise. Edited by - clabinsky on December 29, 2001 2:46:03 AM Edited by - clabinsky on December 29, 2001 2:50:39 AM
Why make it simple when you can make it sooo nice and complicated?
Advertisement
Well, as far as I can tell there are two possibilities here. Either I have misunderstood your post, or you have misunderstood the implementation of Singleton-classes. If it''s the first, I appologize, otherwise this might be helpful:

  class Singleton {public:  static Singleton* getInstance() {    if (instance == null)      instance = new Singleton();    return instance;  }  // Other public methods hereprotected:  Singleton() : instance(NULL) {    // Stuff  }private:  Singleton* instance;};// In order to use the Singleton in another source-file you// need to include the proper header, and in order to access// the Singleton''s methods and such you do this:Singleton* aSingleton = Singleton::getInstance();// This usage guarantees that there can only ever be one// object of the type Singleton, and that all instances of// Singleton is in fact the same object.  


Notice that the constructor is protected so that a new instance can only be created through the static getInstance method.

-Neophyte

- Death awaits you all with nasty, big, pointy teeth. -

Neophyte forgot to make the instance* member static...

you can also use this bit of code instead:
  class Singleton {	protected:			Singleton() {}	public:		virtual ~Singleton() {}	public:		//the instance is created on the first call		static Singleton *getInstance() {			static Singleton the_instance;			return &the_instance;		}}  
I prefer kvh''s method since the prior method (using new) leaves it up to some client to delete the singleton. If you''re OK with having the singleton exist for the entire length of the program from the time you first call getInstance, kvh''s code is the way to go.
quote:Original post by Stoffel
I prefer kvh''s method since the prior method (using new) leaves it up to some client to delete the singleton. If you''re OK with having the singleton exist for the entire length of the program from the time you first call getInstance, kvh''s code is the way to go.


I disagree. If you have multiple singletons access each other then you run into problems because you can''t be certain which static instance will be destroyed first, thus you could run into a dead reference problem.

For example (shamelessly ripped from Modern C++ Design), you have Keyboard and Log singletons. The Keyboard gets used right away so it''s static variable is instantiated. The logging class doesn''t get used until later. Now you decide to shutdown the application. Static variables get destructed in a FILO order, and since the Log singleton was instantiated after the Keyboard singleton it will be destroyed before the Keyboard singleton. Now if the Keyboard singleton has an error on shutdown and tries to access the Log singleton, boom.

IMO, you are better off to use pointers and explicitely delete them at program shutdown in the order you need them to be deleted.


- Houdini

- Houdini
If singletons need to be shutdown in a specific order, then you are right. Otherwise, the static method is cleaner, and you don''t have to worry about explicitly shutting it down.


Mike
"Unintentional death of one civilian by the US is a tragedy; intentional slaughter of a million by Saddam - a statistic." - Unknown
Ok, thanks a lot for your replies, however it seems I have not explained my worries too good

First of all, I do understand the implementation and by the way I prefer the way kvh solves the problem, no new for me thanks.

What I am really looking for is to see the differences between using a global and using a Singleton. Now, lets assume that the singleton class has been created according to kvh.

To use the singleton outside classes (in loop etc) I do:
#define GlobalSingleton Singleton::getInstance()

So to call a function in the Singleton I just GlobalSingleton.DoWhatIWant();

Now, my problem starts when another class wants to use the Singleton. Correct me if I am wrong but the class that uses the Singleton must:

1. have the header included: #include "Singleton.h"
2. define a member like Singleton *m_Singleton; (maybe not a must)

Then to use the singleton withing the class, I initiate m_Singleton, but how? I tried:

m_Singleton=Singleton::getInstance();

But the compiler complains on the = operator.

I guess I could just call it by Singleton::getInstance().Something() but I would much rather have a pointer to the real Singleton saved in the class to avoid typing and extra function call. What am I doing wrong?

Now, this class is clearly dependent on the Singleton because it is going to use the Singletons functions. I know this could be a highly rated stupid question but: is this dependecy unavoidable?

Appreciate your replies guys.

OK OK! My reading is kind of lazy I saw you comment Neophyte. This becomes sort of a class global then, eh?

I am actually a Swede, living in paradise.

Edited by - clabinsky on December 29, 2001 4:39:33 PM
Why make it simple when you can make it sooo nice and complicated?
i'm afraid i still don't really understand your question, but you can save the singleton-pointer in a class like this:

          class Singleton {        //the constructor is protected, so an object can only         //be created inside this class	protected:		Singleton() {}	public:		virtual ~Singleton() {}	public:		static Singleton *getInstance() {			static Singleton the_instance;			return &the_instance;		}	public:		void doSomething() {}};class SingletonUser {	public:		SingletonUser() {			singleton_ptr = Singleton::getInstance();		}		virtual ~SingletonUser() {}	public:		void useSingleton() {			singleton_ptr->doSomething();		}	private:		Singleton *singleton_ptr;};int main() {	SingletonUser user;	user.useSingleton();	return 0;}          


if that doesn't do it, show us a bit of code, and tell us the error-message the compiler gives you

you'll have to elaborate on the part about the dependency...

EDIT:
quote:
OK OK! My reading is kind of lazy I saw you comment Neophyte. This becomes sort of a class global then, eh?

ah, your edit makes this post completely useless then

Edited by - kvh on December 29, 2001 5:22:17 PM
Ok, sorry but the questions are not well written. I think that my problem is so trivial that it does not even look like a problem. I might be doing the right thing cause it works, but I want to know what is happening.

quote:Original post by kvh

            class Singleton {        //the constructor is protected, so an object can only         //be created inside this class	protected:		Singleton() {}	public:		virtual ~Singleton() {}	public:		static Singleton *getInstance() {			static Singleton the_instance;			return &the_instance;		}	public:		void doSomething() {}};  


Ok, one (edit:several) question(s) here. Shouldn´t you, or must you not have a member variable declared in the above? like so:

static Singleton *instance;

AND

if you declare a member variable does it not have to be the same as in *getInstance() ie: the_instance?? If not, when does it get initiated? Does this implicitly happen when getInstance get called and

static Singleton the_instance;

runs?

WHAT I HAVE DONE SO FAR:
In the classes who uses the Singletons I have:

private:
CScreen *m_cScreen;

AND initiate them in a function like so:
m_cScreen=CScreen::GetInstance(); and this seems to work fine.

Here is my Singleton, it differs a little from yours (of course):
  class CScreen:public CSurfBase{private:	LPDIRECTDRAWSURFACE7 m_lpPrimary;	LPDIRECTDRAWSURFACE7 m_lpSecondary;protected:	CScreen()  {Clear();};	static CScreen m_cScreen;//When does it initiate? public:	~CScreen() {Destroy();};		bool Create();	bool Destroy();	bool Clear();	static CScreen* GetInstance()	{		static CScreen rObj;//Initiate m_cScreen?		return &rObj	}};      


Lets wrap this up, I appreciate your still keeping up kvh.


Edited by - clabinsky on December 29, 2001 5:32:05 PM

Edited by - clabinsky on December 29, 2001 5:33:28 PM
Why make it simple when you can make it sooo nice and complicated?
i think you''re a bit confused by the use of static

in C++, keywords often have different meanings depending on the context where they are used:

a static member variable is a variable that you can access without creating an object of the class, so it''s shared among all objects of a class

you can also make variables that are local to a function static, the variable is created when you call the function for the first time, and stays alive for the rest of the program

take a look at this example:

  #include <iostream>using namespace std;void printCounter() {	//executed only the first time this	//function gets called	static int counter = 0;	//executed on every call	counter++;	cout << counter << endl;}int main() {	for(int i=0; i<5; ++i)		printCounter();	return 0;}  


see? the Singleton is a created as a local variable to the getInstance() method, but since it is not destroyed when the function exits, and we can still use it afterwards, we just return a pointer to this variable

This topic is closed to new replies.

Advertisement