Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Re: Limit Object Instances (http://www.velocityreviews.com/forums/t267759-re-limit-object-instances.html)

Dhruv 06-26-2003 01:06 PM

Re: Limit Object Instances
 
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.




Evan 06-26-2003 06:20 PM

Re: Limit Object Instances
 
"Dhruv" <dhruvbird@gmx.net> wrote in message news:<pan.2003.06.26.13.06.18.68842@gmx.net>...
> 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).

Dhruv 06-27-2003 01:29 PM

Re: Limit Object Instances
 
On Thu, 26 Jun 2003 11:20:14 -0700, Evan wrote:

> "Dhruv" <dhruvbird@gmx.net> wrote in message news:<pan.2003.06.26.13.06.18.68842@gmx.net>...



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.







Evan 06-28-2003 04:20 AM

Re: Limit Object Instances
 
"Norbert Riedlin" <nr@netatec.de> wrote in message news:<vqlhdb.pn4.ln@netserv.ka.netatec>...
> "Evan" <eed132@psu.edu> schrieb im Newsbeitrag
> news:3f25c666.0306261020.5e1a55e7@posting.google.c om...
> ...
> > 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
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=


Ramon 06-28-2003 10:10 PM

Re: Limit Object Instances
 
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 06-28-2003 10:16 PM

Re: Limit Object Instances
 
<forgot one quetion>
Is there a naming convention for singleton classes?



Dhruv 07-02-2003 08:06 AM

Re: Limit Object Instances
 
On Thu, 26 Jun 2003 11:20:14 -0700, Evan wrote:

> "Dhruv" <dhruvbird@gmx.net> wrote in message news:<pan.2003.06.26.13.06.18.68842@gmx.net>...



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.








All times are GMT. The time now is 08:01 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.