Singleton Pattern, C++

Started by
22 comments, last by MaulingMonkey 16 years, 10 months ago
Hi, I have a problem. I read about singleton design pattern and got the idea, but lets say I want to develop a CLog class. Class that will log everything I need and put in a file. I want to do this class Singleton. This class will have, hmm lets say a static method: statics CLog* Instance(const char* filename); When this method called file with given filename will be created(if needed) and opened. Next there will be some methods like write to file and etc. Now at the end when program exit I need to close this file, free some allocated memory (if was allocated). But the only way to do it as I see is by created a new method like Exit(); that will do all this. The problem is this method need to be called bu user and its not behaving like class destructor. Is there any option to created some function that will be called automatically when Singleton will be destroyed? Or maybe if constructor and destructor declared as private/protected they will be called any way when object created/destroyed? Thanks.

I would love to change the world, but they won’t give me the source code.

Advertisement
Don't use a singleton. If you feel you must, try a shared_ptr.
"I'd rather know one thing, no matter how ordinary, than discourse endlessly on great issues." -- Galileo
I wish I was at my computer, so that I could show you my logFile class. Basically my class was a non-singleton, that you didn't have to pass references too. It also formatted output like this:

00:12:82 [PHYSICS]: Loading physics engine.
00:12:82 [PHYSICS]: Initializing physics engine.
00:12:82 [PHYSICS]: Physics engine initialized.
>00:12:82 [PHYSICS]: <ERROR> Couldn't execute collision.

To display it would be something like this;

log_file lf("log1.log", "physics");

lf << "Loading physics engine.";
lf << "Initializing physics engine.";
lf << "Physics engine initialized.";
lf.error("Couldn't execute collision.");


All you have to do is #include "log_file.hpp", and you could use the code like that. The benefit (one of many) of the non-singleton, was the fact that you could log to many different files, like this:

log_file lf1("logger1.txt");
log_file lf2("logger2.txt");

lf1 << "Yeah!";
lf2 << "Yeah!";

And everything would work fine.

Also, it's not global, so you don't have to worry about thing getting into the global namespace, which is nice.

I'd think of a way to design something similar to that above, as it works great for me.

"I'd rather know one thing, no matter how ordinary, than discourse endlessly on great issues." -- Galileo
Ok I got your idea but lets discuss another class: CApplication class.
Formally I (or user whatever =\ ) can create only one application so there I need to use singleton (or maybe there is another way something like shared_ptr as you said before [Didn't checked it yet]).

I would love to change the world, but they won’t give me the source code.

Quote:Original post by s.kwee
Formally I (or user whatever =\ ) can create only one application

Why?
Quote:Original post by Sneftel
Quote:Original post by s.kwee
Formally I (or user whatever =\ ) can create only one application

Why?

Because logically there can be only one application.
Even if not I want to limit number of applications to one, I'm designing software and thats how I want it to behave.

I would love to change the world, but they won’t give me the source code.

Quote:Original post by s.kwee
Quote:Original post by Sneftel
Quote:Original post by s.kwee
Formally I (or user whatever =\ ) can create only one application

Why?

Because logically there can be only one application.
Even if not I want to limit number of applications to one, I'm designing software and thats how I want it to behave.


Don't create more than one. Have you ever "accidentally" created an instance of something when you didn't plan to? It is pretty hard to in C++, given that you have to declare variables.

It would take *extra work* for you to impose such a limit on your program. That extra work could contain bugs. Would your extra code handle tearing down and creating a new Application object without terminating the process?

I have several objects in my game which only have one instance at a time. But there isn't any code guarding that. I could create 2 renderers, 2 world objects etc.

What does the Application object do anyway? What are its responsibilities?
Quote:Original post by s.kwee
Because logically there can be only one application.

Then create only one. The singleton should only be used where it would literally be logically impossible to create more than one. Hint: There are extremely few situations where singletons are appropriate. If you aren't developing for an embedded platform, it's likely that in your application there are none at all.
First: You have described factory pattern.

Second: The fact that you're limiting user to launching one instance of an application is completely unrelated to how many CApplication instances there can be.

Third: All the allocation/deallocation problems are exactly why singletons are so hated. It will, at very best, depend on compiler as to when what and how something is de-allocated.

Singleton logger looks like this:
class CLog{public:  static CLog *instance( void )  {    return &m_instance;  }  ~CLog()  {    // this will be called whenever  }private:  CLog( const char *filename )   {    // open file for writing, etc.  }  static CLog m_instance;}CLog CLog::m_instance( "filename" );


Of course, at this point you'll ask: How do I dynamically determine the filename to write to. You can't. Period. Or you use another singleton from which you obtain it, which will read it from configuration.

class CLog{public:  static CLog* instance( const char* filename );}


Is a factory. It is completely unrelated to singletons in any way. It maintains a state, it caches (or not) instances created, it may or may not be responsible for cleanup.

But most importantly - every call to instance() can return different instance of CLog*. As such, it's unrelated to singleton, which must, on every call to its instance method, return exactly the same instance.
Ok I got the main idea.
But anyway I can tell you "Why to do class pure virtual? Just don't create object from this class and there is no need to do it pure virtual." Its the same.

Quote:
All the allocation/deallocation problems are exactly why singletons are so hated.

So if there is no method to track and free(if needed) objects when Singleton destroyed so I prefer not to use it.

I would love to change the world, but they won’t give me the source code.

This topic is closed to new replies.

Advertisement