Nokurn wrote:
The order in which global objects (such as an instance static) are initialized is not guaranteed. You may have a singleton that depends on another singleton, but the dependent singleton is initialized first. By using lazy evaluated singletons, you ensure that singletons are initialized in the proper order (at least, in single-threaded code). It also guarantees destruction.
I didn't realize this. Makes sense.
Nokurn wrote:
If your code is single-threaded, the correct way to go about implementing a singleton goes something like this:
class Singleton {
public:
static Singleton& instance();
private:
Singleton();
// These declarations ensure that the
// Singleton class is non-copyable.
// Attempting to copy through a
// copy-constructor or assignment
// operator will result in compiler errors
// (due to the private declarations) for
// client code and linker errors for
// Singleton implementation code (due to
// these declarations not being defined).
//
// In C++11, these would be marked =delete.
Singleton(const Singleton&);
Singleton& operator =(const Singleton&);
};
Singleton& Singleton::instance()
{
static Singleton inst;
return inst;
}
Singleton::Singleton()
{
// By using a private constructor, you ensure that
// the class may only be instantiated within itself.
// In this case, it is not possible to instantiate a
// Singleton in client code, so the only Singleton
// instance in the entire program is the one
// instantiated in the Singleton::instance() function.
}
I appreciate the example. That is really helpful. I've Implemented a manager similar to this in a shoot em up game I wrote a while back but in all honesty, I had no idea why I was doing it. I came across it reading someone elses code and it looked like an easy way to access something globally.
Nokurn wrote:
As for your destructor problem, place debug prints around each for_each loop to help narrow it down. Unless sf::Music::stop() is the source of the issue, I suspect that your Deallocator functors are the problem.
I did this and it is definitely the for loop. The functors are fine. I just ended up removing it and it seems to work. I'm not sure how sfml handles music internally and if it even really matters if I delete the sound without stopping it. I'm not getting any errors so I assume its ok.
Nokurn wrote:
Edit: I would like to include my recommendation against using a singleton. I would advise the use of individual sound managers that store related pools of sounds and directly passing the managers to their users. This would allow you to implement more fine-grained control of resources; you could have a pool of sounds that must be available for the duration of the program's execution and pools that exist only for a particular level's lifetime, which are destroyed when the level is completed.
So you mean, having maybe a sound manager for the game class and individual sound managers for each level or area? Then if I needed to have a sound when the character shoots or jumps or something like that, just pass a reference to character for the appropriate sound manager? I suppose that will end up making the dependencies more explicit.
I know there is a good reason for not using singletons and globally available objects but I am just missing it. I would imagine understanding that peice of the puzzle is the key for me to start designing better code. Can you point me in the direction of some design patterns that would be beneficial for me to start studying?
"Do I really have to spell this out? What if a bunch of punk kids go into the woods with a bullet proof vest and strap it on a grizzly bear? Then what have you got? Invincible bears. Is that what you want? Invincible bears running around; raping your churches and burning your women?"