Make it a 'singleton' template managerWell now that you understand how the 'normal' template works, here is the implementation of the 'singleton' template: template <class T, int n> class TPersistentManager { public: TPersistentManager(void); ~TPersistentManager(void); int Add(const T* p_T); int Delete(const T* p_T); int Delete(int index); int DeleteAll(); T* Get(int index); T* Get(const T* p_T); Int GetCount(); int GetError(); char *GetErrorString(); private: static int refcount; static TManager<T, n> *p_m_tManager; }; // Note that you MUST initialize these for correct functionality template <class T, int n> int TPersistentManager<T, n>::refcount = 0; template <class T, int n> TManager<T, n>* TPersistentManager<T, n>::p_m_tManager = 0x00000000; template <class T, int n> TPersistentManager<T, n>::TPersistentManager(void) { if(refcount == 0) { p_m_tManager = new TManager<T, n>; } refcount++; } template <class T, int n> TPersistentManager<T, n>::~TPersistentManager(void) { refcount--; if(refcount == 0) { delete p_m_tManager; p_m_tManager = 0x00000000; } } template <class T, int n> int TPersistentManager<T, n>::Add(const T* p_T) { return p_m_tManager->Add(p_T); } // . // . Rest of code omitted… see the attached code files // . template <class T, int n> char *TPersistentManager<T, n>::GetErrorString() { return p_m_tManager->GetErrorString(); } Now this class does some crucial work, it makes sure that there is only one TManager pointer in the TPersistentManager template. It also redirects all functions to use that TManager class for performing its actions. Note that this redirection is needed because otherwise you cannot make your own class deriving from this so that it can use the functions. If you were to try that with the TManager it would just allocate new variables for each instance of the your class. Also note that it keeps a reference count to determine wheter the last instantiation of the class was released, in which case all memory for the managed objects is released as well. How to use it for your own typesOkay that is all nice, but now the question remains: "How can I use it?" The answer to that question is rather simple: you just instantiate a class the same way you would instantiate a normal template class. Here is an example to make it clear: class CImageSystem : public TPersistentManager<CImage, 128> { public: CImageSystem(); ~CImageSystem(); . // Functions you want to make specific for the CImageSystem class . . } And now you can create multiple instances of the CImageSystem class in different files and they will still use the same CImageSystem class (which is the property of a singleton class). EvaluationAlthough this code might seem a bit messy (and I cannot deny it is) it allows you to easily create managers for all kind of data structures without having to rewrite code. And although the extra function calling in the TPersistentManager class might seem like overhead (and it is), if you have a good compiler it will inline these functions for you, resulting in close to 0% function calling overhead in some cases. ConclusionWell I do not think that I can say anything here that isn't obvious yet. There are really only two choices. You can use this approach, or you can use another approach. I really do not want to say that this is the best way to manage data, but at least it is a way (and in my opinion a rather good one). If there are any people out there with suggestions, comments or remarks, please feel free to email me at: e.j.folkertsma@student.utwente.nl SourceHere is the source. Note that this probably isn't the best code possible. I wrote it in 60 minutes or so with some retouching (since I didn't mean to send it along in the first place) to make it readable. |
|