Developing A Once-Only Initialised Class
Posted
by David McClarnon
on December 4th, 2002
Often, we need a once-only initialised class that is global to the entire system. Examples of such a class would be the loading of a library, or options from the Registry.
This is a base class which provides (a) an initialisation, only if the class is used and (b) ensures a once-only instance for the application.
template <class CLASS>
class CStaticClass
{
public:
virtual ~CStaticClass() { };
static CLASS &Get()
{
static CLASS m_theObject;
m_theObject.Initialise();
return m_theObject;
}
void Initialise()
{
if (!m_fInitialised)
{
OnInitialise();
m_fInitialised = TRUE;
}
}
protected:
CStaticClass()
{
m_fInitialised = FALSE;
}
virtual void OnInitialise() = 0;
private:
BOOL m_fInitialised;
} ;
An example of use would be for loading a library:
class CMyLibrary : public CStaticClass<CMyLibrary>
{
public:
CMyLibrary()
{
m_hLibrary = NULL;
m_pfnFunction = NULL;
}
virtual ~CMyLibrary()
{
if (m_hLibrary != NULL)
{
::FreeLibrary(m_hLibrary);
}
}
void DoFunction()
{
if (m_pfnFunction != NULL)
{
m_pfnFunction();
}
else
{
ASSERT(FALSE);
}
}
protected:
virtual void OnInitialise()
{
m_hLibrary = ::LoadLibrary("mylibrary.dll");
if (m_hLibrary != NULL)
{
m_pfnFunction = ::GetProcAddress(m_hLibrary, "MyProc");
}
}
private:
HMODULE m_hLibrary;
FARPROC m_pfnFunction;
} ;
So, to call the designated function, use this line of code:
CMyLibrary::Get().DoFunction();

Comments
This doesn't work at all, sloppy idea.
Posted by Legacy on 12/04/2002 12:00amOriginally posted by: Pass over
Try the following testing program, you will see that your method doesn't work at all, you have a totally wrong idea of control singleton:
void main()
{
printf("size = %d\n", sizeof(CMyLibrary));
CMyLibrary lib1, lib2, lib3;
printf("address: lib1 = %d, lib2 = %d, lib3 = %d\n", &lib1, &lib2, &lib3);
printf("address2: lib1 = %d, lib2 = %d, lib3 = %d\n",
&lib1.Get(), &lib2.Get(), &lib3.Get());
}
Reply
The drawbacks
Posted by Legacy on 12/04/2002 12:00amOriginally posted by: Darwen
I should have added the drawbacks of this method -
To make it work you have to either
(a) have the constructor of the inherited classes as public
or
(b) declare CStaticClass as a friend of the inherited class
For (b) e.g. -
class CMyInheritedClass
: public CStaticClass<CMyInheritedClass>
{
public:
virtual ~CMyInheritedClass()
private:
CMyInheritedClass();
friend CStaticClass<CMyInheritedClass>;
};
If you use (a) then people can create more than one instance of the class, if you use (b) they can't.
Darwen.
ReplyA.k.a singleton pattern
Posted by Legacy on 12/04/2002 12:00amOriginally posted by: Per
Reply