Thread: Singleton

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    19

    Singleton

    Given my code...

    widgetman.h
    Code:
    class WIDGETMANAGER{
        public:
            ~WIDGETMANAGER();
            WIDGETMANAGER();
            
            static WIDGETMANAGER* instance();
    
        private:
            std::vector<WIDGET*> widgets;
            static WIDGETMANAGER* pInstance;
            
        protected:
            WIDGETMANAGER(const WIDGETMANAGER&);
            WIDGETMANAGER& operator= (const WIDGETMANAGER&);
            
    };
    widgetmanager.cpp
    Code:
    WIDGETMANAGER* WIDGETMANAGER::pInstance = 0;
    
    WIDGETMANAGER::WIDGETMANAGER(){
        std::cout << "WIDGET MANAGER INITIALIZED\n";
        this->x = 0;
    }
    
    WIDGETMANAGER::~WIDGETMANAGER(){
        int numWidgets = this->widgets.size();
        int deleteCount = 0;
        for(int i = 0; i < numWidgets; i++){
            if(this->widgets[i]){
                delete this->widgets[i];
                deleteCount++;
            }
        }
        std::cout << "WIDGET MANAGER DESTROYED [" << deleteCount << " WIDGETS DESTROYED]\n";
    }
    
    WIDGETMANAGER* WIDGETMANAGER::instance(){
        if(!WIDGETMANAGER::pInstance){
            WIDGETMANAGER::pInstance = new WIDGETMANAGER();
        }
        return WIDGETMANAGER::pInstance;
    }
    Now in WIDGET::WIDGET()
    Code:
    this->widgetManInstance = WIDGETMANAGER::instance();
    I'm getting WIDGET MANAGER INITIALIZED output for every WIDGET I create.

    I initialized WIDGETMANAGER in another class, the first instance. So shouldn't every other instance be the same? Or am I just not getting this whole idea.

  2. #2
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Looks like you are creating multiple instances of widgetmanager to me. Each time you create a widget it has a manager attached to it if I am seeing the problem correctly. Each manager is a seperate instance, which you don't want. You want to create only 1 manager instance and then register instances of widgets to it. You'd need to create a addWidget() function to the manger class.

    Code:
    WIDGETMANAGER myWidgetManager;
    
    Widget *wp = new Widget();
    
    myWidgetManager.addWidget(wp);
    or something similar...

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You want WIDGETMANAGER to be a singleton, who's address is returned by WIDGETMANAGER::instance(). To achieve that, you need to prevent any WIDGETMANAGER from being created unless it's address is returned by the instance method.

    The way to achieve that is to make it's constructor and destructor private. In your code which either creates widgets (or possibly in the widget class) that will probably trigger a compiler error, which will lead you to the problem --- which I suspect is some code creating a WIDGETMANAGER by some means other than calling the instance() function.

    Given this line in your constructor;
    Code:
    this->x = 0;
    which would guarantee your code doesn't compile, I suspect the code you've provided is incomplete or doing something you haven't shown.

  4. #4
    Registered User
    Join Date
    Jul 2006
    Posts
    19
    Yeah sorry I removed that code because I used 'x' to test the instance by setting it in the widget constructor and in the first instance I made to determine they were in fact different instances. I didn't want to have anything confusing the problem at hand, missed a bit. It is removed from my code anyway it was just a small temporary stub.

    My aim is to indeed add an addWidget(Widget*) member but as I have this multiple instance problem I haven't moved on to that.

    I try to make the constructor and destructor private but I get an error saying that the constructor is private.

  5. #5
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    I don't see a problem.
    Code:
    class WIDGETMANAGER
    {
        public:
            static WIDGETMANAGER* instance();
            int x;
    
        private:
            ~WIDGETMANAGER();
            WIDGETMANAGER();
            
            static WIDGETMANAGER* pInstance;    
    };
    
    WIDGETMANAGER* WIDGETMANAGER::pInstance = NULL;
    
    WIDGETMANAGER::WIDGETMANAGER()
    {
        std::cout << "WIDGET MANAGER INITIALIZED" << std::endl;
        this->x = 0;
    }
    
    WIDGETMANAGER::~WIDGETMANAGER()
    {
        std::cout << "WIDGET MANAGER DESTROYED" << std::endl;;
    }
    
    WIDGETMANAGER* WIDGETMANAGER::instance(){
        if(!WIDGETMANAGER::pInstance){
            WIDGETMANAGER::pInstance = new WIDGETMANAGER();
        }
        return WIDGETMANAGER::pInstance;
    }
    
    int main()
    {
            WIDGETMANAGER *mgr = WIDGETMANAGER::instance();
            std::cout << mgr->x << std::endl;
            mgr->x = 4;
    
            WIDGETMANAGER *mgr2 = WIDGETMANAGER::instance();
            std::cout << mgr2->x << std::endl;
    
            return 0;
    }
    Quote Originally Posted by Smallz
    I try to make the constructor and destructor private but I get an error saying that the constructor is private.
    The only place the constructor should be called is from inside the class. If it's being called anywhere else, replace it with WIDGETMANAGER::instance().
    Last edited by pianorain; 09-12-2006 at 11:04 AM.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  6. #6
    Registered User
    Join Date
    Jul 2006
    Posts
    19
    Quote Originally Posted by pianorain
    The only place the constructor should be called is from inside the class. If it's being called anywhere else, replace it with WIDGETMANAGER::instance().
    Bullseye, and if I had posted all relevant code this probably would have been solved earlier. That makes absolutely perfect sense but at the time I just didn't really see what was taking place, it's so simple yet for some reason I just didn't fully understand, (well I thought I did but I missed a bit obviously), what was happening in the code till you said that... God I'm stupid sometimes.

    Thanks a lot people./

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Singleton template problem
    By cloudy in forum C++ Programming
    Replies: 14
    Last Post: 01-11-2009, 05:40 AM
  2. How To Derive from a singleton
    By appleGuy in forum C++ Programming
    Replies: 8
    Last Post: 03-24-2007, 01:55 PM
  3. Templated singleton classes
    By VirtualAce in forum C++ Programming
    Replies: 2
    Last Post: 07-01-2006, 04:06 AM
  4. Thread-safe singleton.
    By Hulag in forum C++ Programming
    Replies: 3
    Last Post: 06-14-2006, 10:45 AM
  5. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM