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

  • On-demand Event Event Date: July 22, 2015 Today's increasingly mobile workforce creates new challenges for organizations that rely heavily on collaboration. Businesses need to be both secure and collaborative, and they can't sacrifice one over the other. The plethora of devices and clouds used by mobile employees only complicates these challenges. Watch this webcast and learn how your business can enable mobile access to files from anywhere while it helps to maintain information governance, compliance, and …

  • How to give users what they want AND maintain control, visibility, and security. File sync and share is everywhere. In the past decade, cloud-based storage and syncing solutions have exploded to fill a growing need for anytime, anywhere access to everything from photos and videos to documents, spreadsheets, and PDFs. We understand that choosing any new service or tool can be a lengthy and complex process. That's why we've created this buyer's guide to help make your evaluation process a little bit easier. In …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date