Re: Limit Object Instances

Discussion in 'C++' started by Dhruv, Jun 26, 2003.

  1. Dhruv

    Dhruv Guest

    On Thu, 26 Jun 2003 05:41:22 -0700, amitpethkar wrote:

    > Hi All,
    >
    > I want to know is it possible to limit the instances of C++ class.
    > for example
    > Suppose there is 1 instance created of a class and if you create
    > other instances they will refer to 1st instance itself instead of
    > constructing more objects



    Create a static object. Or create a static object within the class of the
    same type as the class.

    -Dhruv.
     
    Dhruv, Jun 26, 2003
    #1
    1. Advertising

  2. Dhruv

    Evan Guest

    "Dhruv" <> wrote in message news:<>...
    > Create a static object. Or create a static object within the class of the
    > same type as the class.
    >
    > -Dhruv.


    Both of these have drawbacks. First, by "create a static object" I
    assume you mean one whose members are all static. However, static
    functins are not virtual, so inheritance is crippled. Second, if you
    object has initialization tasks, since there is no constructor, your
    code has to be responsible for calling in Itin() method or similar.
    Better to leave as few responsibilities to the client code as
    possible. Same deal with the destructor. Adding a static object also
    has issues; I'll discuss those after giving a quick overview of the
    "correct" solution, the singleton (as Dimitris Kamenopoulos
    mentioned).

    You have your class:

    class myClass (
    public:
    void DoStuff();
    // blah blah blah... your other functions

    Instead of using the new operator and the constructor in client code
    (i.e. myClass* myObject;) you'll call an Instance function (myClass
    myObject = myClass::Instance();). This has to be static.
    (Unfortunately in some views at least, you'll find when dealing with
    "Design Patterns" such as the singleton you'll be using lots of
    pointers.)

    myClass& Instance() {
    if (_instance == NULL)
    _instance = new myClass;
    return _instance;
    }

    This is often done with pointers (i.e. Instance() will return a
    myClass*), but this way will keep the client code from deleting it and
    breaking everything. (This is actually prevented, even in this code,
    my making the destructor private, but returning a reference keeps the
    temptation away.) So much for the public interface.

    private:
    myClass* _instance;

    This holds the pointer to the one object that is created. Now you have
    a class the supports the singleton pattern. However, it doesn't
    enforce it; client code can still createobjects of tye myClass. To
    keep that from happening, we need to make thi constructors private,
    even if you don't supply any (or C++ will provide you with them...
    it'l like lawyers. "If you do not provide a constructor one will be
    provided for you." Sorry.) Remember that this is in the private area
    of the class.

    myClass() {}
    myClass(const myClass& arg) {}

    (Both a zero-argument and copy constructor.) Also provided by the
    compiler: the assignment operator.

    myClass& operator=(const myClass&)
    {return *_instance;}

    The last thing to do is prevent people from deleting the objects (yes,
    it's still possible even with the version of Instance() we use):

    ~myClass() {}
    };

    There's your singleton.




    It's now possible to say why using a static object, rather than a
    pointer is a bad idea. First, here are the changes to the class file:

    // stuff...
    myClass& Instance() {
    return _instance;
    }
    private:
    static myClass _instance;
    // more stuff...


    Now suppose you have the following code in another file:

    int aGlobalVariable =
    myClass::Instance().SomeFunctionThatReturnsAnInt();

    The result is undefined because the construction order of the
    _instance variable in myClass and aGlobalVariable is undefined. If
    aGlobalVariable is constructed first, it will have a dead reference.

    Second, if your object has large start up/tear down tasks then they
    will be carried out regardless if the object is ever used.


    Many thanks to both the Gang of Four's "Design Patterns" and Andrei
    Alexandrescu's "Modern C++ Design" (which provided the problems with
    both static implementations, as well as the reasoning for returning a
    reference rather than a pointer).
     
    Evan, Jun 26, 2003
    #2
    1. Advertising

  3. Dhruv

    Dhruv Guest

    On Thu, 26 Jun 2003 11:20:14 -0700, Evan wrote:

    > "Dhruv" <> wrote in message news:<>...



    Hey, thanks :) I myself was unaware of this approach. It's somewhat like
    virtual constructors, but without the virtual. I've been thinking of
    getting hold of that book for a while, and this seems to be the right
    time.

    Regards,
    -Dhruv.
     
    Dhruv, Jun 27, 2003
    #3
  4. Dhruv

    Evan Guest

    "Norbert Riedlin" <> wrote in message news:<>...
    > "Evan" <> schrieb im Newsbeitrag
    > news:...
    > ...
    > > myClass& Instance() {
    > > if (_instance == NULL)
    > > _instance = new myClass;
    > > return _instance;
    > > }

    >
    > Obviously you meant
    > return *_instance
    >


    Oopsie... yes I did. Originally I had Instance returning a pointer
    rather than a reference, but changed it after I had typed it. (This is
    also why some of the wording of the surrounding text may seem a little
    weird...)



    Anyway, the rest of this is in reference to the remainder of your
    comments (reproduced below as I have little to add and what I say
    could get lost). I have nothing specific to add except to add a big
    thank you for the info. It's only very recently that I've been
    learning this material myself--I bought Design Patterns only within
    the last two and a half weeks, and read the chapter in Alexandrescu's
    book last weekend--so this stuff is new to me as well. I particularily
    like the static local variable in Instance.

    I just have one question. You say that often the implementation of the
    assignment operator and I guess copy constructor are usually
    omitted... wouldn't this produce a linker error? Or just if they are
    called in client code? Or what's the deal?


    > > This is often done with pointers (i.e. Instance() will return a
    > > myClass*), but this way will keep the client code from deleting it and
    > > breaking everything. (This is actually prevented, even in this code,
    > > my making the destructor private, but returning a reference keeps the
    > > temptation away.) So much for the public interface.
    > >
    > > private:
    > > myClass* _instance;
    > >
    > > This holds the pointer to the one object that is created. Now you have
    > > a class the supports the singleton pattern. However, it doesn't
    > > enforce it; client code can still createobjects of tye myClass. To
    > > keep that from happening, we need to make thi constructors private,
    > > even if you don't supply any (or C++ will provide you with them...
    > > it'l like lawyers. "If you do not provide a constructor one will be
    > > provided for you." Sorry.) Remember that this is in the private area
    > > of the class.
    > >
    > > myClass() {}
    > > myClass(const myClass& arg) {}
    > >
    > > (Both a zero-argument and copy constructor.) Also provided by the
    > > compiler: the assignment operator.
    > >
    > > myClass& operator=(const myClass&)
    > > {return *_instance;}

    >
    > Often the implementation of these methods is omitted. Only a declaration is
    > provided.
    >
    > >
    > > The last thing to do is prevent people from deleting the objects (yes,
    > > it's still possible even with the version of Instance() we use):
    > >
    > > ~myClass() {}
    > > };
    > >
    > > There's your singleton.
    > >
    > > It's now possible to say why using a static object, rather than a
    > > pointer is a bad idea. First, here are the changes to the class file:
    > >
    > > // stuff...
    > > myClass& Instance() {
    > > return _instance;
    > > }
    > > private:
    > > static myClass _instance;
    > > // more stuff...
    > >
    > >
    > > Now suppose you have the following code in another file:
    > >
    > > int aGlobalVariable =
    > > myClass::Instance().SomeFunctionThatReturnsAnInt();
    > >
    > > The result is undefined because the construction order of the
    > > _instance variable in myClass and aGlobalVariable is undefined. If
    > > aGlobalVariable is constructed first, it will have a dead reference.
    > >
    > > Second, if your object has large start up/tear down tasks then they
    > > will be carried out regardless if the object is ever used.
    > >
    > >

    >
    > What you say is all correct, but I would like to present another alternative
    > (and some of its gotchas)
    > The interface of the Instance method will be the same as in your example
    > but:
    > class myClass {
    > //...
    > myClass& Instance() {
    > static myClass instance;
    > return instance;
    > }
    > //...
    > };
    >
    > First of all: never begin an identifier with an underscore. There are too
    > many things to remember, which identifiers are reserved for the
    > implementation and which may be used by your application. So better don't do
    > that.
    > Second: no 'if' involved, no dynamic memory usage. The disadvantage of
    > constructing instance_ at startup also disappears, it will be constructed,
    > as soon as Instance() is called for the first time.
    > Third: (not shown): the member variable 'instance_' (in your example
    > '_instance') vanishes from the class declaration.
    > Fourth (and not so obvious): 'instance's destructor will be called when the
    > application is going down. This may or may not be a good thing. You cann do
    > some cleanup, logging, writing persistence data, but imagine other
    > singletons, that depend on 'instance' when they shut down. On the othjer
    > hand, when you need the destructor being called, you have no other choice.
    > Fifth: The calling of the destructor has another implication: A private
    > destructor is ok according to the standard, but some compilers just don't
    > get it right (MSVC 6.0). Logically the destructor is called in the context
    > of Instance(), which has acces rights, but the code is generated somewher in
    > main()'s epilogue. Sigh, to be portable you have to stick with a public
    > destructor...
    >
    > With the implications above and when you don't need 'instance's destructor
    > beeing called, I would stick to the following implication:
    > class myClass {
    > //...
    > myClass& Instance() {
    > static myClass* instance = new myClass();
    > return *instance;
    > }
    > //...
    > };
    >
    > Essentially the implementation is then the same as yours, bearing the lack
    > of the member variable. (and the missing 'if')
    >
    > > Many thanks to both the Gang of Four's "Design Patterns" and Andrei
    > > Alexandrescu's "Modern C++ Design" (which provided the problems with
    > > both static implementations, as well as the reasoning for returning a
    > > reference rather than a pointer).

    >
    > Yeah, I would like to thank them too!
    >
    > Norbert
    >
    >
    >
    > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    > *** Usenet.com - The #1 Usenet Newsgroup Service on The Planet! ***
    > http://www.usenet.com
    > Unlimited Download - 19 Seperate Servers - 90,000 groups - Uncensored
    > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
     
    Evan, Jun 28, 2003
    #4
  5. Dhruv

    Ramon Guest

    Is there any standard (or de facto standard) way to write a singleton
    class?
    Is there any template we need to use for this classes?
     
    Ramon, Jun 28, 2003
    #5
  6. Dhruv

    Ramon Guest

    <forgot one quetion>
    Is there a naming convention for singleton classes?
     
    Ramon, Jun 28, 2003
    #6
  7. Dhruv

    Dhruv Guest

    On Thu, 26 Jun 2003 11:20:14 -0700, Evan wrote:

    > "Dhruv" <> wrote in message news:<>...



    Hey, thanks :) I myself was unaware of this approach. It's somewhat like
    virtual constructors, but without the virtual. I've been thinking of
    getting hold of that book for a while, and this seems to be the right
    time.

    Regards,
    -Dhruv.
     
    Dhruv, Jul 2, 2003
    #7
    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. Dimitris Kamenopoulos

    Re: Limit Object Instances

    Dimitris Kamenopoulos, Jun 26, 2003, in forum: C++
    Replies:
    1
    Views:
    822
    amitpethkar
    Jun 27, 2003
  2. John Wohlbier
    Replies:
    2
    Views:
    369
    Josiah Carlson
    Feb 22, 2004
  3. Replies:
    1
    Views:
    1,089
    Victor Bazarov
    Jun 28, 2005
  4. Replies:
    8
    Views:
    470
    James Stroud
    Jan 29, 2009
  5. Jonathan Wood
    Replies:
    6
    Views:
    477
    Jonathan Wood
    May 5, 2009
Loading...

Share This Page