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

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: November 13, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT APIs can be a great source of competitive advantage. The practice of exposing backend services as APIs has become pervasive, however their use varies widely across companies and industries. Some companies leverage APIs to create internal, operational and development efficiencies, while others use them to drive ancillary revenue channels. Many companies successfully support both public and private programs from the same API by varying levels …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds