Which class comes first?
Greetings!
I have a situtation like this:
file: CLog.h
class CLog : public mySingleton<CLog>
{
public:
CLog()
{
opens log file etc...
}
}
file: CDriver.h
class CDriver : public mySingleton<CDriver>
{
public:
CDriver()
{
CLog::GetInstance()->WriteLog("Driver started.\n");
}
}
The problem is, CDriver starts earlier as CLog. Both are declared in CPP files like this:
(CLog.cpp): static CLog myLog;
(CDriver.cpp): static CDriver myDriver;
Whitout "static" my intel compailer will complain. This is for a library. Is there any way, I could ensure myLog gets initiated earlier as CDriver? Except i could encapsulate cLog into cDriver. But i don't wanna do that at the moment.
Thank you in advance!
No, there isn't and it's called the initialization order problem.
Dare I suggest not using singletons? I'm sure static methods will be just fine.
In any case, you could stick instances of all the classes in a class anyway, something like this; thus stating the initialization order. I think so anyway, check the standard to see if it actually follows the initialization order given in the initializer list, because now that I think about it, it might not. ISO 14882/1998, probably somewhere around 8.5 or 12.1, maybe 3.6.2.
In Singleton.h and Singelton.cpp (or whereever)
Now someone generalize this throughly fugly piece of code, and generally improve it [grin].
The mySingleton class now doesn't have to do any instantiation itself.
[1] Gonkulator
Dare I suggest not using singletons? I'm sure static methods will be just fine.
In any case, you could stick instances of all the classes in a class anyway, something like this; thus stating the initialization order. I think so anyway, check the standard to see if it actually follows the initialization order given in the initializer list, because now that I think about it, it might not. ISO 14882/1998, probably somewhere around 8.5 or 12.1, maybe 3.6.2.
In Singleton.h and Singelton.cpp (or whereever)
//Singleton.h/* mySingleton doesn't need to instantiate the class because it's done in InitOrderInstance*/template<class T>class mySingleton{public: T& GetInstance();};//Singleton.cppnamespace{class InitOrder{ CDriver m_Driver; CFlombulator m_Flombulator; CGonkulator m_Gonkulator; //see footnote 1public: CLog() : m_Driver(), m_Flombulator(), m_Gonkulator() {} // Can anyone think of a better way to do this? template<class T> void Get(T const*&) { throw UnknownClassException(); } template<> void Get(CDriver const*& p) { p = &m_Driver; } template<> void Get(CFlombulator const*& p) { p = &m_Flombulator; } template<> void Get(CGonkulator const*& p) { p = &m_Gonkulator; } CDriver& Driver(){ return m_Driver(); } CFlombulator& Flombulator(){ return m_Flombulator(); } CGonkulator& Gonkulator(){ return m_Gonkulator(); }} InitOrderInstance; };template<class T>T& mySingleton::GetInstance(){ T* p; ::InitOrderInstance.Get(p); return *p;}
Now someone generalize this throughly fugly piece of code, and generally improve it [grin].
The mySingleton class now doesn't have to do any instantiation itself.
[1] Gonkulator
The answer is to use explicit initialization for your singletons:
Something like this
Basically you shouldn't use any static variables before main starts (i.e. no static variable should rely on any other static variable for initialization).
Something like this
int main(){ CLog::create();//CLog::getInstance() will not work before this statement CDriver::create();//can rely on CLog being available}
Basically you shouldn't use any static variables before main starts (i.e. no static variable should rely on any other static variable for initialization).
Quote:Original post by MrEvil
In any case, you could stick instances of all the classes in a class anyway, something like this; thus stating the initialization order. I think so anyway, check the standard to see if it actually follows the initialization order given in the initializer list, because now that I think about it, it might not. ISO 14882/1998.
Members are guaranteed to be initialised in the order they are declared in the class definition.
OP: If you don't need guaranteed order of destruction (i.e. CDriver does not write to CLog in its destructor), I'd be tempted just to go for a Meyer's Singleton:
class CLog{ public: static CLog & instance(); // useful member functions private: CLog(); CLog(CLog const &);};CLog & CLog::instance(){ static CLog clog; return clog;}CLog::CLog(){ // initialisation}
Enigma
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement