Singletons Singletons are evil, at least, that's what everyone seems to say. But like anything, they have their place. Singletons are object classes that guarantee at least two things: 1. One and only one object can be instantiated, and 2. A global access point to that instantiation will be provided. The problem some see with singletons is that the idiom can be overused; they are, essentially, global objects, and many try to avoid global objects like the plague. But sometimes singletons are practical, and logical, even necessary. Consider a logger or kernel. It makes sense that only one of these object classes need be instantiated at any one time, and for most applications, it would also be necessary to provide a global point of access to them - all parts of an application might want to log information or request kernel services at some point. There are a few ways to control object instantiation. Here's a simple example of the 'static member procedure' method, using a bare-bones logger class. First, the code: Code: type Logger public: declare static function GetInstance () as Logger ptr ' ... private: declare constructor () declare constructor (byref as Logger) declare destructor () declare operator let (byref as Logger) ' ... end type function Logger.GetInstance () as Logger ptr static theinstance as Logger return @theinstance end function The idea is to create a static member procedure that contains a static singleton object - theinstance - which it then returns the address of. Static variables and objects are created when they are first encountered - the first time Logger.GetInstance is called - and are destroyed when the program ends. This has the benefit of delaying creation of the singleton object until it is needed, and also guaranteeing its existence thereafter. All constructors - in this case the default and copy constructor - as well as the destructor and assignment operator are declared private, to prevent user code from creating, copying or destroying Logger objects; only Logger member procedures are allowed to do that. In fact, in this small example, the copy constructor and assignment operator are not even defined. That's the basic idea, here is the rest of Logger's TYPE and member procedure definitions: Code: type Logger public: ' .. as before .. declare function Open (byref filename as string, byval doAppend as integer = -1) as integer declare sub Close () declare sub Log (byref text as string) private: ' .. as before .. const m_invalidFilenum as integer = &Hdeadc0de m_filenum as integer = m_invalidFilenum end type constructor Logger () end constructor destructor Logger () this.Close() end destructor function Logger.Open (byref filename as string, byval doAppend as integer) as integer var filenum = ..freefile() var res = iif (doAppend, _ ..open(filename, for append, as filenum), _ ..open(filename, for output, as filenum)) m_filenum = iif (res, m_invalidFilenum, filenum) return res end function sub Logger.Close () if (m_filenum <> m_invalidFilenum) then ..close(m_filenum) m_filenum = m_invalidFilenum end if end sub sub Logger.Log (byref text as string) if not (m_filenum = m_invalidFilenum) then print #m_filenum, text end if end sub The default constructor does nothing in this example. Logger.Open opens a file for logging, appending to it by default. Logger.Log logs text to the file and Logger.Close closes the file. Here is an example of usage: Code: scope var thelogger = Logger.GetInstance() if (thelogger->Open("filename.txt")) then print "error: Could not open log file." end -1 end if thelogger->Log("some text") thelogger->Log("some more text") thelogger->Close() end scope