|
|
The main problem doing a singleton like that, is that the main class is not a real singleton...
I mean: when you declare: SingletonT<myobject>,
you don't prevent any instanciation of MyObject, everyone are still alowed to do: MyObject a, b, c.
You should do the reverse:
class MyObject: public Singleton...
and after:
MyObject *pobj = MyObject::getInstance() ;
|
|
|
|
|
Thanks for regard
Yes. you are right.
so CObj( test class ) has protected creator.
you can select your class to be a singleton or not.
I did think that is good for pluggable design.
( - Separated code for Object and Singleton )
but other guys dislike it
in my case, i think it is good, so i use it.
anyway... thanks for regard again!
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
|
Great link
Jonathan de Halleux, Belgium.
|
|
|
|
|
To make the template more 'user-friendly', I suggest to make all constructors and destructors private, so the user can neither create a singleton himself, nor destroy it accidentally (delete CSingletonT<CObj>::GetObject(); ):
template <class _objT>
class CSingletonT : public _objT
{
private:
CSingletonT(){}
CSingletonT(const CSingletonT&);
CSingletonT& operator=(const CSingletonT&);
virtual ~CSingletonT(){}
public:
};
Additionally, making the singleton a static member, is not a good idea. Since C++ does not define the order of initialization for dynamically initialized objects, following code may fail:
int g_nGlobal = CSingletonT<CObj>::GetObject()->x; A better approach is to use a static pointer in CSingletonT .
Regards
Thomas
Sonork id: 100.10453 Thömmi
Disclaimer: Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.
|
|
|
|
|
Thanks in advance, Thomas. your advance is really reasonable.
but I wonder something about ur advance.
in the first, I can't find any problem with below code
int g_nGlobal = CSingletonT<CObj>::GetObject()->x;
In my VC, it's works well..
I hope more explanation for problem situation.
and, I didn't hope CSingletonT use like general passing variable.
I think, no need to copy CSingletonT itself. like function parameter..
( copy constructor, or assignment operator override... )
when singleton give some object, then singleton work is end, then no need to do with singleton, i think.
and the reason why i use static member but not static pointer, is some user want to do something to clean up in CObj.
CObj maybe open file or kernel resource. user want to close thats in CObj's destructor or save at last in file, registry.
but if CSingletonT use static pointer, then no chance to clean up for them easily.
thanks a lot, and i hope your reply.
|
|
|
|
|
Cho, Kyung-min wrote:
in the first, I can't find any problem with below code
int g_nGlobal = CSingletonT<cobj>::GetObject()->x;
In my VC, it's works well..
I hope more explanation for problem situation.
It may work well as long as both the singleton and the g_nGlobal are in the same translation unit (i.e. .cpp resp. .obj file). But as soon as they are in different units, the initialization order is undetermined, so the code can work correctly, but it's not guaranteed.
Cho, Kyung-min wrote:
and the reason why i use static member but not static pointer, is some user want to do something to clean up in CObj.
CObj maybe open file or kernel resource. user want to close thats in CObj's destructor or save at last in file, registry.
but if CSingletonT use static pointer, then no chance to clean up for them easily.
Then I would recommend the atexit function:
template <class _objT>
class CSingletonT : public _objT
{
private:
CSingletonT(){}
CSingletonT(const CSingletonT&);
CSingletonT& operator=(const CSingletonT&);
virtual ~CSingletonT(){}
static _objT* pObj_;
static void DestructSingleton() { delete pObj_; }
public:
static _objT* GetObject()
{
if (!pObj_)
{
pObj_ = new _objT;
atexit (DestructSingleton);
}
return pObj_;
}
};
template <class _objT>
_objT* CSingletonT<_objT>::pObj_ = NULL; The only impact with above solution is the dead reference problem, i.e. if the destructor of one singleton tries to access another singleton, which is already destroyed.
Regards
Thomas
Sonork id: 100.10453 Thömmi
Disclaimer: Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.
|
|
|
|
|
Thomas Freudenberg wrote:
The only impact with above solution is the dead reference problem, i.e. if the destructor of one singleton tries to access another singleton, which is already destroyed.
You need the nifty counter pattern for that.
http://www.gamedev.net/columns/gameengineering/singleton/
|
|
|
|
|
Yhanks, Robin
now i have a good reference about singletone
i will check it
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
Thomas Freudenberg wrote:
Since C++ does not define the order of initialization for dynamically initialized objects, following code may fail:
Why? AFAIK, the constructor for static object declared in GetObject will be invoked on first call to GetObject(). Am I missing something?
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Tomasz Sowinski wrote:
Since C++ does not define the order of initialization for dynamically initialized objects, following code may fail:
You checked the Thomas answer to Cho ?
quoting from Thomas
It may work well as long as both the singleton and the g_nGlobal are in the same translation unit (i.e. .cpp resp. .obj file). But as soon as they are in different units, the initialization order is undetermined, so the code can work correctly, but it's not guaranteed.
This is even a greater issue within Multhreading issues , since Singleton implementation is even harder ...
A known solution is using the double-checked pattern with atomic processor specific instructions (Multiprocessor scenarios) to guarantee proper Singleton behaviour ...
Cheers,
Joao Vaz
A Programming Language is a tool that has profound influence on our thinking habits -The late giant Edsger Dijkstra 1930 - 2002
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary. -
|
|
|
|
|
Joao Vaz wrote:
You checked the Thomas answer to Cho ?
I did. But the author of the article uses classic 'Meyers singleton', with object living as static variable in static member function. The order of initialization is guaranteed by C++.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Tomasz Sowinski wrote:
But the author of the article uses classic 'Meyers singleton', with object living as static variable in static member function.
Ops, true ,just checked the source code ... damn vacations !!!
But what I said in Multithread scenarios still aplly , this singleton is fine, but in MT scenarios it could be broken .
Particularly if two threads make the same call to initialize the singleton, in this case you must protect it to guarante proper one-time initialization of the singleton object. This is done for instance in Boost.Threads and Posix Win32 threads port, they use also a unique system or process wide name to guarantee this one time initialization.
Cheers,
Joao Vaz
A Programming Language is a tool that has profound influence on our thinking habits -The late giant Edsger Dijkstra 1930 - 2002
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary. -
|
|
|
|
|
Tomasz Sowinski wrote:
Why? AFAIK, the static object's constructor declared in GetObject will be invoked on first call to GetObject(). Am I missing something?
Oops. I was missing something. Most implementations of the Singleton Pattern use a static class member, so I did see over it.
Mea culpa.
Regards
Thomas
Sonork id: 100.10453 Thömmi
Disclaimer: Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.
|
|
|
|
|
Stop a second. I'm not understanding what you wrote.
...
CSingletonT(){}
CSingletonT(const CSingletonT&);
CSingletonT& operator=(const CSingletonT&);
We are talking about singletons. By definition there should be only one instance of a object of this class. Right?
Then, why in hell do you propose copy and assignment constructors ?????
What did i miss?
Andreas
int x=1, y=5;
x^=y^=x^=y;
|
|
|
|
|
Andreas Saurwein wrote:
Then, why in hell do you propose copy and assignment constructors ?????
They are only declared, but not implemented, so the user gets a linker error, as soon as he assigns a singleton to another.
IMHO singleton are used mostly to prevent others to misuse your code. If you use your code only on your own, singleton are mostly superfluous.
Regards
Thomas
Sonork id: 100.10453 Thömmi
Disclaimer: Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.
|
|
|
|
|