Sign in to follow this  
Samurai Jack

Which class comes first?

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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)

//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.cpp
namespace
{

class InitOrder
{
CDriver m_Driver;
CFlombulator m_Flombulator;
CGonkulator m_Gonkulator; //see footnote 1
public:
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

Share this post


Link to post
Share on other sites
The answer is to use explicit initialization for your singletons:

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).

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this