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

  • 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
  • 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
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.

  • When individual departments procure cloud service for their own use, they usually don't consider the hazardous organization-wide implications. Read this paper to learn best practices for setting up an internal, IT-based cloud brokerage function that service the entire organization. Find out how this approach enables you to retain top-down visibility and control of network security and manage the impact of cloud traffic on your WAN.

Most Popular Programming Stories

More for Developers

RSS Feeds

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