Sign in to follow this  
yedda_2000

Singleton - having problems

Recommended Posts

I've got a program that is supposed to require one object of class mySingletonObject, and this object needs to be available from anywhere in the program. The object is created in the main function, and it does work to stop another from being made within main. However, mySingleton object contains members made from other classes, which inturn contain members made from other classes, which contain functions that need to get information from the mySingletonObject in which they are nested. I wanted to avoid having to pass the mySingleton object into these functions, simply because the way things are interconnected I would endlessly be passing this reference between multiple classes/functions to get it to the function that actualy needs it. It seemed far easier to create the object as a singleton (sort of a pseudo global), since I only wanted one anyway. The problem is that an object nested within the mySingleton object seems to be able to create more mySingleton objects. Even worse, because one of these objects is created in the constructor of an object that is created in the mySingleton object , and then in turn looks for the mySingleton object (calling the funtion that should either return the reference or create a new object), the program ends up in an endless reiteration of constructors. The mySingleton object creates an object which doesn't recongnize that a mySingleton object already exists, so it creates another mySingleton object, which creates an object which doesn't recongnize that a mySingleton object already exists... This is basic code: //mySingleton.h #ifndef CLASS_MYSINGLETON_H #define CLASS_MYSINGLETON_H #include "Nest.h" //A Singleton class, this should be able to only be instanced once class mySingleton { public: static mySingleton* Instance(); static void Destroy(); protected: mySingleton(); mySingleton(const mySingleton&); mySingleton& operator= (const mySingleton&); ~mySingleton(); private: static mySingleton* _instance; Nest* nest; int size; }; #endif //CLASS_MYSINGLETON_H //mySingleton.cpp #include "mySingleton.h" mySingleton* mySingleton::_instance = 0; mySingleton::mySingleton() { this->nest = new Nest; this->size = rand() % 10; } mySingleton::~mySingleton() { delete this->nest; } mySingleton* mySingleton::Instance() { if(_instance == 0) { _instance = new mySingleton; } return _instance; } void mySingleton::Destroy() { delete _instance; _instance = 0; } //Nest.h #ifndef CLASS_NEST_H #define CLASS_NEST_H #include "Egg.h" class Nest { public: Nest(); ~Nest(); private: Egg* egg; }; #endif //CLASS_NEST_H //Nest.cpp #include "Nest.h" Nest::Nest() { this->egg = new Egg; } . . . //Egg.h #ifndef CLASS_EGG_H #define CLASS_EGG_H class Egg { public: Egg(); ~Egg(); private: int type; }; #endif //CLASS_EGG_H //Egg.cpp #include "mySingleton.h" Egg::Egg() { this->type = mySingleton::Instance()->size; } . . . //main.cpp #include "mySingleton.h" int main(int argc, char *argv[]) { mySingleton* tree = new mySingleton; } As far as I know, mySingleton::Instance() should not be creating a new object when one already exists. Can anyone tell me why it is? Is there a better way to accomplish what I want? Thanx

Share this post


Link to post
Share on other sites
You built yourself a nice dependency chain here.

The error is that you don't set the static instance pointer in the singletons constructor. Therefor the Egg will create a second singleton with the Instance call.

Share this post


Link to post
Share on other sites
You don't have any singletons there. They are just classes with unusual construction patterns.

- Singletons are never instantiated - you call getInstance method to obtain a reference to an instance
- You never pass pointers to singletons around. That's the whole point. They exist in one place
- Singletons do not have copy constructors or assignment operators (or they are declared private) - why provide them, when they may not be copied.


template < class T >
class Singleton
{
public:
static T &getInstance()
{
static T instance();
return instance;
}
private:
Singleton() {}
}

struct Egg
{
void foo() {}
}

typedef Singleton<Egg> EggSingleton;

...

EggSingleton::getInstance().foo();




Of course, this won't solve the problem of circular dependencies, but that's a different issue.

Share this post


Link to post
Share on other sites
Two corrections for Antheus:
  1. static T instance();

    With the parentheses, it's considered to be a function (and an incorrect one at that, since it's qualified at static yet isn't at global scope).

  2. Singletons may be passed around using pointers or references in an useful way—for instance, when the singleton is derived from a non-singleton base class.

Share this post


Link to post
Share on other sites
oops, that main function in my code should have read

//main.cpp
#include "mySingleton.h"
int main(int argc, char *argv[])
{
mySingleton* tree = mySingleton::Instance();
}

which is what is in my actual code. Should't have been posting at 1:30 am.
So with that, I should be creating an instance the first time Instance() is called, and thus setting _instance to the address of this new instance. Yes?

The egg doesn't just create a second instance of the object. It creates an infinite amount because of the dependancies.

Antheus:
I'm putting my copy and assignment constructors under protected so the object can't be copied. Should these be under private?

Anyway, I realized that the egg is making instances of the singleton because the singleton hasn't finished making itself (it is still making the egg, which is done in the singleton's constructor), so _instance doesn't have an address in it yet. Solved the problem by first creating the singleton, then initializing the nest and egg.

mySingleton's constructor now looks lke this:
mySingleton::mySingleton()
{
Nest* nest = NULL;//doesn't really need to be here. just filler
}

and main looks like this:
{
mySingleton::Instance()->nest = new Nest;
}

Thanx for the help, guys.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this