Singleton question

Discussion in 'C++' started by JFR, Jun 30, 2005.

  1. JFR

    JFR Guest

    i found this code sample on the net that i wanted to use:




    class CUniqueObject
    {
    private:
    CUniqueObject( void ) : m_iValue(0) { }
    ~CUniqueObject( void ) { }


    public:
    void SetValue( int iValue ) { m_iValue = iValue; }
    int GetValue( void ) { return m_iValue; }

    static CUniqueObject *GetInstance( void )
    {
    if( m_pSingleton == 0 )
    {
    std::cout << "creating singleton." << std::endl;
    m_pSingleton = new CUniqueObject;
    }
    else
    {
    std::cout << "singleton already created!" << std::endl;
    }

    return m_pSingleton;
    }

    static void Kill( void )
    {
    if( m_pSingleton != 0 )
    {
    delete m_pSingleton;
    m_pSingleton = 0;
    }
    }


    private:
    int m_iValue;
    static CUniqueObject *m_pSingleton;
    };


    CUniqueObject *CUniqueObject::m_pSingleton = 0;


    int main( int argc, char *argv[] )
    {

    CUniqueObject *pObj1, *pObj2;
    pObj1 = CUniqueObject::GetInstance();
    pObj2 = CUniqueObject::GetInstance();
    pObj1->SetValue( 11 );
    std::cout << "pObj1::m_iValue = " << pObj1->GetValue() << std::endl;
    std::cout << "pObj2::m_iValue = " << pObj2->GetValue() << std::endl;
    pObj1->Kill();

    return 0;
    }


    when i run the above code and debug it, the pObj1 shows that it
    contains 2 things, a m_iValue and a m_pSingleton. However, the
    m_pSingleton contains a CUniqueObject* which in turns also contains a
    m_iValue and a m_pSingleton, and this goes on and on. I can expand the
    object trees in the debugger infinitely.
    At first i thought there was a problem with the code, but i think it's
    just the debugger's way of showing objects.

    Is this behavior "normal"?
     
    JFR, Jun 30, 2005
    #1
    1. Advertising

  2. JFR

    Rolf Magnus Guest

    JFR wrote:

    > i found this code sample on the net that i wanted to use:
    >
    >
    >
    >
    > class CUniqueObject
    > {
    > private:
    > CUniqueObject( void ) : m_iValue(0) { }
    > ~CUniqueObject( void ) { }


    There should also be (deliberately not implemented):

    CUniqueObject(CUniqueObject&);
    void operator=(CUniqueObject);

    to avoid accidental copies of the object.

    > public:
    > void SetValue( int iValue ) { m_iValue = iValue; }
    > int GetValue( void ) { return m_iValue; }
    >
    > static CUniqueObject *GetInstance( void )
    > {
    > if( m_pSingleton == 0 )
    > {
    > std::cout << "creating singleton." << std::endl;
    > m_pSingleton = new CUniqueObject;
    > }
    > else
    > {
    > std::cout << "singleton already created!" << std::endl;
    > }
    >
    > return m_pSingleton;
    > }
    >
    > static void Kill( void )
    > {
    > if( m_pSingleton != 0 )
    > {
    > delete m_pSingleton;
    > m_pSingleton = 0;
    > }
    > }
    >
    >
    > private:
    > int m_iValue;
    > static CUniqueObject *m_pSingleton;
    > };
    >
    >
    > CUniqueObject *CUniqueObject::m_pSingleton = 0;
    >
    >
    > int main( int argc, char *argv[] )
    > {
    >
    > CUniqueObject *pObj1, *pObj2;
    > pObj1 = CUniqueObject::GetInstance();
    > pObj2 = CUniqueObject::GetInstance();
    > pObj1->SetValue( 11 );
    > std::cout << "pObj1::m_iValue = " << pObj1->GetValue() << std::endl;
    > std::cout << "pObj2::m_iValue = " << pObj2->GetValue() << std::endl;
    > pObj1->Kill();
    >
    > return 0;
    > }
    >
    >
    > when i run the above code and debug it, the pObj1 shows that it
    > contains 2 things, a m_iValue and a m_pSingleton. However, the
    > m_pSingleton contains a CUniqueObject* which in turns also contains a
    > m_iValue and a m_pSingleton, and this goes on and on. I can expand the
    > object trees in the debugger infinitely.
    > At first i thought there was a problem with the code, but i think it's
    > just the debugger's way of showing objects.


    Yes, it is. The object only contains m_iValue. m_pSingleton is a static
    member, which means it's only there once for the whole class and not for
    every instance of it.

    > Is this behavior "normal"?


    The debugger should be more precise.
     
    Rolf Magnus, Jun 30, 2005
    #2
    1. Advertising

  3. "JFR" <> schrieb:

    > when i run the above code and debug it, the pObj1 shows that it
    > contains 2 things, a m_iValue and a m_pSingleton. However, the
    > m_pSingleton contains a CUniqueObject* which in turns also contains
    > a m_iValue and a m_pSingleton, and this goes on and on. I can expand
    > the object trees in the debugger infinitely. At first i thought
    > there was a problem with the code, but i think it's just the
    > debugger's way of showing objects.
    >
    > Is this behavior "normal"?


    Yes, it is. It's just the expected behaviour of the debugger handling
    variables containing pointers to itself.

    BTW: I've never been a friend of constructions like this class you
    used. For some reasons:

    a) Private constructors forbid the creation of sub-classes. This can
    cause serious problems if anyone tries to recycle this class for
    later use.

    b) Methods like GetInstance() cause several problems:

    - They hide the way an object is created. A programmer does never
    know, is the object created now or has it been created long before
    and should he delete it or is it deleted automatically, is it
    created on the heap at all and so on. This methods forbid several
    ways to create an instance. One time I found the following methods
    of several classes in the same class library: GetInstance(),
    GetObject(), CreateObject() and NewObject(). One of them used
    reference counting on creation. Which one was it?

    - GetInstance() does not allow to call a specific constructor. In this
    case several different methods would be needed. Indeed programmers
    do implement initialization methods rather and call them after
    calling GetInstance(). This leads to a two-step-construction in the
    best case. In worst case they "initialize" the existing singleton
    again and again. We could ask if a singleton is really the right
    concept here.

    What the hell is evil on "new"?

    void foo ()
    {
    MyClass* pMyClass=new MyClass("bla",1.234);
    // ...
    delete pMyClass;
    }

    And why not use a local instance of a class on the stack for a local
    purpose?

    void foo ()
    {
    MyClass c("bla",1.234); // make it just static to
    // get a singleton!
    // ...
    }

    In my experience the singleton pattern is normally enforced by people
    having found this just a really gorgeous idea and not knowing real
    problems.

    T.M.
     
    Torsten Mueller, Jun 30, 2005
    #3
  4. Torsten Mueller skrev:
    > "JFR" <> schrieb:
    >
    >
    >>when i run the above code and debug it, the pObj1 shows that it
    >>contains 2 things, a m_iValue and a m_pSingleton. However, the
    >>m_pSingleton contains a CUniqueObject* which in turns also contains
    >>a m_iValue and a m_pSingleton, and this goes on and on. I can expand
    >>the object trees in the debugger infinitely. At first i thought
    >>there was a problem with the code, but i think it's just the
    >>debugger's way of showing objects.
    >>
    >>Is this behavior "normal"?

    >
    >
    > Yes, it is. It's just the expected behaviour of the debugger handling
    > variables containing pointers to itself.
    >
    > BTW: I've never been a friend of constructions like this class you
    > used. For some reasons:
    >
    > a) Private constructors forbid the creation of sub-classes. This can
    > cause serious problems if anyone tries to recycle this class for
    > later use.


    I get you point, but is this really a problem?
    Is anyone likely to inherit a class that is directly
    implemented as a singleton?
    Singleton _templates_ on the other hand...

    I'm just curious, not picking a fight.
    >
    > b) Methods like GetInstance() cause several problems:
    >
    > - They hide the way an object is created. A programmer does never
    > know, is the object created now or has it been created long before
    > and should he delete it or is it deleted automatically, is it
    > created on the heap at all and so on. This methods forbid several
    > ways to create an instance. One time I found the following methods
    > of several classes in the same class library: GetInstance(),
    > GetObject(), CreateObject() and NewObject(). One of them used
    > reference counting on creation. Which one was it?
    >
    > - GetInstance() does not allow to call a specific constructor. In this
    > case several different methods would be needed. Indeed programmers
    > do implement initialization methods rather and call them after
    > calling GetInstance(). This leads to a two-step-construction in the
    > best case. In worst case they "initialize" the existing singleton
    > again and again. We could ask if a singleton is really the right
    > concept here.
    >
    > What the hell is evil on "new"?
    >
    > void foo ()
    > {
    > MyClass* pMyClass=new MyClass("bla",1.234);
    > // ...
    > delete pMyClass;
    > }
    >
    > And why not use a local instance of a class on the stack for a local
    > purpose?
    >
    > void foo ()
    > {
    > MyClass c("bla",1.234); // make it just static to
    > // get a singleton!
    > // ...
    > }
    >
    > In my experience the singleton pattern is normally enforced by people
    > having found this just a really gorgeous idea and not knowing real
    > problems.
    >
    > T.M.
     
    Pelle Beckman, Jul 2, 2005
    #4
  5. JFR

    JFR Guest

    > In my experience the singleton pattern is normally enforced by people
    > having found this just a really gorgeous idea and not knowing real
    > problems.
    >
    > T.M.


    Mybe you're right. I just needed a class with global scope to do some
    macromanagement of the (complex) application state and resources. I
    want to make clean code that is gonna be extensible and
    straightforward. The singleton pattern seemed to me like the perfect
    tool. Since I learned about patterns a short while back, I probably
    suffer from pattern obsession disorder, but it's fine since my code is
    purely an exercice in practice. I only hope that if i made bad design
    choices, I'm going to notice them, even if it's much later on, just so
    i dont make the same mistake twice.
     
    JFR, Jul 2, 2005
    #5
  6. JFR

    JFR Guest

    > I get you point, but is this really a problem?
    > Is anyone likely to inherit a class that is directly
    > implemented as a singleton?
    > Singleton _templates_ on the other hand...


    The original code snippet is posted isnt the one i use. I of course
    have no use for a pure singleton class, so i used a templated one that
    goes as follows:



    template <typename T> class CSingleton
    {
    protected:
    CSingleton( void ) { }
    ~CSingleton( void ) { std::cout << "destroying singleton." <<
    std::endl; }


    public:
    static T *GetInstance( void )
    {
    if( m_pSingleton == 0 )
    {
    std::cout << "creating singleton." << std::endl;
    m_pSingleton = new T;
    }
    else
    {
    std::cout << "singleton already created!" << std::endl;
    }

    return ((T *)m_pSingleton);
    }

    static void Kill( void )
    {
    if( m_pSingleton != 0 )
    {
    delete m_pSingleton;
    m_pSingleton = 0;
    }
    }


    private:
    static T *m_pSingleton;

    };

    template <typename T> T *CSingleton<T>::m_pSingleton = 0;





    anyone see some potential improvements on this code and care to
    discuss it?
     
    JFR, Jul 2, 2005
    #6
  7. JFR skrev:
    >>In my experience the singleton pattern is normally enforced by people
    >>having found this just a really gorgeous idea and not knowing real
    >>problems.
    >>
    >>T.M.

    >
    >
    > Mybe you're right. I just needed a class with global scope to do some
    > macromanagement of the (complex) application state and resources. I
    > want to make clean code that is gonna be extensible and
    > straightforward. The singleton pattern seemed to me like the perfect
    > tool. Since I learned about patterns a short while back, I probably
    > suffer from pattern obsession disorder, but it's fine since my code is
    > purely an exercice in practice. I only hope that if i made bad design
    > choices, I'm going to notice them, even if it's much later on, just so
    > i dont make the same mistake twice.
    >


    Pattern Obsession Disorder is a wonderful new word!
     
    Pelle Beckman, Jul 2, 2005
    #7
  8. Pelle Beckman <> schrieb:

    > > a) Private constructors forbid the creation of sub-classes. This
    > > can cause serious problems if anyone tries to recycle this class
    > > for later use.

    >
    > I get you point, but is this really a problem?


    It can be, yes. I got a library from someone implementing a beautiful
    class with private constructors and even a private destructor. I just
    wanted to extend a method by one line of my own code, all the rest and
    also the singleton state of the object should remain as it was. I
    couldn't do this without changing the original class.

    In my opinion the keyword "private" is always (!) bad style.
    "protected" solves the task much better without the disadvantages.

    T.M.
     
    Torsten Mueller, Jul 4, 2005
    #8
  9. "JFR" <> schrieb:

    > > In my experience the singleton pattern is normally enforced by
    > > people having found this just a really gorgeous idea and not
    > > knowing real problems.

    >
    > Mybe you're right. I just needed a class with global scope to do
    > some macromanagement of the (complex) application state and
    > resources. I want to make clean code that is gonna be extensible and
    > straightforward.


    Sure! But this code is the opposite of extensible.

    Look, nobody will forbid you to create a single instance of a class
    for global use. But this class does not need private constructors and
    this stuff at all. Just use a normal class for this.

    T.M.
     
    Torsten Mueller, Jul 4, 2005
    #9
  10. JFR

    Lionel Guest

    Torsten Mueller wrote:
    > In my experience the singleton pattern is normally enforced by people
    > having found this just a really gorgeous idea and not knowing real
    > problems.


    I have had some very good uses for the Singleton pattern in the past.
    Admittedly they were in Java which does have some consequences.

    I can't think of a situation where you would use the Singleton pattern
    and would want to have subclasses, that just sounds crazy IMHO. The idea
    generally is that you only want one instance of some set of data that is
    operated on by everyone, this way it stays consistent.

    I have also never gone looking to just apply a design patter for the fun
    of it, I have always started with a problem and just discovered that a
    particular pattern is suitable for purpose.

    Lionel.
     
    Lionel, Jul 4, 2005
    #10
  11. JFR

    Lionel Guest

    Lionel wrote:
    > Torsten Mueller wrote:
    >
    >> In my experience the singleton pattern is normally enforced by people
    >> having found this just a really gorgeous idea and not knowing real
    >> problems.

    >
    >
    > I have had some very good uses for the Singleton pattern in the past.
    > Admittedly they were in Java which does have some consequences.
    >
    > I can't think of a situation where you would use the Singleton pattern
    > and would want to have subclasses, that just sounds crazy IMHO. The idea
    > generally is that you only want one instance of some set of data that is
    > operated on by everyone, this way it stays consistent.
    >
    > I have also never gone looking to just apply a design patter for the fun
    > of it, I have always started with a problem and just discovered that a
    > particular pattern is suitable for purpose.


    Actually, I possibly didn't read your post carefully enough,
    particularly your discussion of protected instead of private. I would
    agree on that!
     
    Lionel, Jul 4, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Proton Projects - Moin

    Singleton - Whether Cloneable overrides Singleton

    Proton Projects - Moin, Mar 26, 2007, in forum: Java
    Replies:
    4
    Views:
    3,334
    Proton Projects - Moin
    Mar 27, 2007
  2. Wilhelm
    Replies:
    1
    Views:
    185
  3. Trans
    Replies:
    12
    Views:
    304
    Robert Klemme
    Sep 14, 2007
  4. Paul McMahon
    Replies:
    3
    Views:
    221
    David A. Black
    Jun 9, 2008
  5. Charles Oliver Nutter

    Singleton methods without the singleton class

    Charles Oliver Nutter, Mar 15, 2010, in forum: Ruby
    Replies:
    4
    Views:
    220
    Charles Oliver Nutter
    Mar 22, 2010
Loading...

Share This Page