Developing A Once-Only Initialised Class

Environment: Visual C++ Version 6

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();


About the Author

David McClarnon

He first encountered Windows programming using Visual C++/MFC version 1.5 on Windows 3.11 a very long time ago. He is now a contract developer specialising in .NET/native interop with p/invoke.

Comments

  • A.k.a singleton pattern

    Posted by Legacy on 12/04/2002 12:00am

    Originally posted by: Per

    Looks pretty much like a template version of the singleton
    
    design pattern, which is commonly used for ensuring only one instance of a class.

    If you haven't heard of "design patterns" in a programming
    context, search the web for info _now_ :-)


    Example of a typical singleton:

    // MyClass is a singleton and there can thus exist at most
    // 1 instance of it which it basically ensures all by itself.

    MyClass
    {
    public:

    void Bar()
    {
    cout << "Boo!";
    }

    static MyClass* getInstance()
    {
    if (sInstance==0)
    {
    sInstance = new CMyClass()
    }

    return sInstance;
    }

    static void destroyInstance()
    {
    delete sInstance;
    sInstance = 0;
    }

    private:
    // Private constructor to get compile error
    // on "new MyClass" outside the class' scope.
    MyClass() {}
    virtual ~MyClass() {}

    // Copy constructor deliberately not implemented
    explicit MyClass(const MyClass&);

    // Assignment operator deliberately not implemented
    MyClass& operator = (const MyClass&);

    static MyClass* sInstance;
    }; // MyCLass

    // in the .cpp initialize sInstance
    MyClass* MyClass::sInstance = 0;
    .
    .
    .

    // So to use it:
    void SomeFunc()
    {
    MyClass* foo = MyClass::getInstance();

    foo->Bar();

    .
    .
    .

    Reply
  • This doesn't work at all, sloppy idea.

    Posted by Legacy on 12/04/2002 12:00am

    Originally 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:00am

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

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The impact of a data loss event can be significant. Real-time data is essential to remaining competitive. Many companies can no longer afford to rely on a truck arriving each day to take backup tapes offsite. For most companies, a cloud backup and recovery solution will eliminate, or significantly reduce, IT resources related to the mundane task of backup and allow your resources to be redeployed to more strategic projects. The cloud - can now be comfortable for you – with 100% recovery from anywhere all …

  • The latest release of SugarCRM's flagship product gives users new tools to build extraordinary customer relationships. Read an in-depth analysis of SugarCRM's enhanced ability to help companies execute their customer-facing initiatives from Ovum, a leading technology research firm.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds