C++ Singleton problem...

Discussion in 'C++' started by tobias.sturn@vol.at, Jun 15, 2006.

  1. Guest

    Hi!

    I have written this template for making a singleton:
    #define DECLARE_SINGLETON(classname) \
    private: \
    static classname* m_pThis; \
    classname(); \
    class Guard \
    { \
    public: \
    ~Guard() \
    { \
    if(classname::m_pThis != 0 ) \
    delete classname::m_pThis; \
    } \
    }; \
    friend class Guard; \
    public: \
    static classname* getInstance();

    #define DEFINE_SINGLETON(classname) \
    classname* classname::m_pThis=0; \
    classname* classname::getInstance() \
    { \
    static Guard guard; \
    if(m_pThis == 0) \
    { \
    m_pThis = new classname(); \
    } \
    return m_pThis; \
    }

    Now i have a class which uses these macros but now i still i can write
    constructors make them public and i have won nothing...

    class Class
    {
    public:
    Class(int a) {/*i have created an object :(*/
    Class(char a)...
    };;

    How could i make it not possible for the user of the template that he
    cant override the constructor?

    Thanks very much!!
    , Jun 15, 2006
    #1
    1. Advertising

  2. Phlip Guest

    tobias.sturn wrote:

    > Now i have a class which uses these macros but now i still i can write
    > constructors make them public and i have won nothing...
    >
    > class Class
    > {
    > public:
    > Class(int a) {/*i have created an object :(*/
    > Class(char a)...
    > };;


    You can't. The point of classes is to be upgraded and re-used. Deal.

    > How could i make it not possible for the user of the template that he
    > cant override the constructor?


    The mininimal situation worked for me:

    class frob {
    DECLARE_SINGLETON(frob);
    };

    DEFINE_SINGLETON(frob);
    frob::frob() {}
    #include <assert.h>
    #include <stdlib.h>

    int main()
    {
    frob * pFrob = frob::getInstance();
    assert(NULL != pFrob);
    // frob aFrob; // <-- bad
    return 0;
    }

    Now about your style. "Singleton" is the most abused pattern in /Design
    Patterns/, and it's the best candidate for time travel to tell the GOF to
    take it out. I can think of many situations where a program needs only one
    of something, but I can't think of any situation where a program should
    never have more than one of something.

    Next, you should use unit tests (like my main()), and should pass them after
    every edit. This implies that some of your classes should use a mock object
    instead of your singleton. So that implies that tests have legitimate
    reasons to re-use more than one instance of your singleton, to construct
    them with extra data, and to derive from them.

    Next, a Singleton is not an excuse for a global variable. Most clients of
    your singleton should pass it in by reference. They should not rely on it
    floating around in space. So nearly all clients of your singleton should
    accept a reference that your tests can mock.

    Next, you are abusing macros. You should instead abuse templates. Google for
    [c++ singleton template], and get sample code like this:

    http://www.codeproject.com/cpp/singleton_template.asp

    Next, neither your getInstance() nor the one on that page can return a NULL
    pointer, so they should return a reference to the Singleton. Whichever
    pattern you go with, make that small fix.

    Next, I suspect this is the best implementation for the getter:

    static T& Instance()
    {
    static T aT;
    return aT;
    };

    That is well-defined to construct aT at least before the first time the
    function enters, so it fixes the common C++ problem with global variables
    constructing out of order, and fixes it without the odious choice of a 'new'
    call. Other patterns and situations may easily apply here, too.

    After applying any subset of my suggestions, you will have a better program
    with less need to restrict your constructors.

    --
    Phlip
    http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
    Phlip, Jun 16, 2006
    #2
    1. Advertising

  3. Axter Guest

    wrote:
    > Hi!
    >
    > I have written this template for making a singleton:
    > #define DECLARE_SINGLETON(classname) \
    > private: \
    > static classname* m_pThis; \
    > classname(); \
    > class Guard \
    > { \
    > public: \
    > ~Guard() \
    > { \
    > if(classname::m_pThis != 0 ) \
    > delete classname::m_pThis; \
    > } \
    > }; \
    > friend class Guard; \
    > public: \
    > static classname* getInstance();
    >
    > #define DEFINE_SINGLETON(classname) \
    > classname* classname::m_pThis=0; \
    > classname* classname::getInstance() \
    > { \
    > static Guard guard; \
    > if(m_pThis == 0) \
    > { \
    > m_pThis = new classname(); \
    > } \
    > return m_pThis; \
    > }
    >
    > Now i have a class which uses these macros but now i still i can write
    > constructors make them public and i have won nothing...
    >
    > class Class
    > {
    > public:
    > Class(int a) {/*i have created an object :(*/
    > Class(char a)...
    > };;
    >
    > How could i make it not possible for the user of the template that he
    > cant override the constructor?
    >
    > Thanks very much!!


    With the following Singleton class, you can create a Singleton use one
    of two methods.
    You can derive from Singleton as the foo example class does below, or
    you can create a class like the Widget example class.

    template<typename T>
    class Singleton
    {
    protected:
    Singleton(){}
    ~Singleton(){}
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
    public:
    class FriendClass
    {
    public:
    FriendClass():m_MyClass(new T()){}
    ~FriendClass(){delete m_MyClass;}
    T* m_MyClass;
    };
    static T& Instance() {
    static FriendClass Instance;
    return *Instance.m_MyClass;
    }
    };

    class Widget {
    private:
    Widget(){}
    ~Widget(){}
    Widget& operator=(const Widget&);
    Widget(const Widget&);
    public:
    friend class Singleton<Widget>::FriendClass;
    int m_i;
    };


    class foo : public Singleton<foo>{
    private:
    foo(){}
    ~foo(){}
    foo& operator=(const foo&);
    foo(const foo&);
    public:
    friend class FriendClass;
    int m_i;
    };


    int main(int argc, char* argv[])
    {
    Widget& MyWidget = Singleton<Widget>::Instance();
    foo& Myfoo = foo::Instance();

    system("pause");
    return 0;
    }
    Axter, Jun 16, 2006
    #3
  4. Phlip Guest

    Axter wrote:

    You answered the wrong question. (I do that often enough I'm going to
    crack down on you for it.)

    > class Widget {
    > private:
    > Widget(){}
    > ~Widget(){}


    One can still write 'public: Widget(something)' here, and construct the
    Widget without the Singleton wrapper.

    --
    Phlip
    Phlip, Jun 16, 2006
    #4
  5. Axter Guest

    Phlip wrote:
    > Axter wrote:
    >
    > You answered the wrong question. (I do that often enough I'm going to
    > crack down on you for it.)
    >
    > > class Widget {
    > > private:
    > > Widget(){}
    > > ~Widget(){}

    >
    > One can still write 'public: Widget(something)' here, and construct the
    > Widget without the Singleton wrapper.
    >


    Then you would not be creating a Singleton.
    Widget is the target Singleton. When you create a Singleton, you want
    your constructors to be private.
    Axter, Jun 18, 2006
    #5
  6. Phlip Guest

    Axter wrote:

    > Then you would not be creating a Singleton. Widget is the target
    > Singleton. When you create a Singleton, you want your constructors to be
    > private.


    That's the design answer (which I already provided). The technical answer
    is you can't prevent Widget from having other constructors.

    --
    Phlip
    Phlip, Jun 18, 2006
    #6
    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,237
    Proton Projects - Moin
    Mar 27, 2007
  2. Wilhelm
    Replies:
    1
    Views:
    162
  3. Trans
    Replies:
    12
    Views:
    273
    Robert Klemme
    Sep 14, 2007
  4. Paul McMahon
    Replies:
    3
    Views:
    204
    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:
    199
    Charles Oliver Nutter
    Mar 22, 2010
Loading...

Share This Page