Advertisement

Templates and inheritence

Started by October 13, 2000 07:44 AM
8 comments, last by The_Minister 24 years, 2 months ago
Note that singletons are described in Game Artchitecture and Design. Here''s the situation: I want an interface (class not intended for use other than inheretence from) which makes classes that derive from it become singletons, let''s call it ISingleton. Now, because there are two types of singletons (ones which initialize at the start of the program and ones which initialize on first use) and I will be using both, it would be benificial to create ISingleton as an abstract base interface and derive ISingletonAtFirst and ISingletonAtStart from it, with slightly different definitions complying with the above requirements. So I could now derive my class from either ISingletonAtFirst or ISingletonAtStart, depending on which I think would work best. Here''s the problem: The ISingleton-derived interfaces both have a function called GetInstance(), both of which return an alias to the singleton, also known as its intance. The alias has to be of the same type as the singleton, ie if my singleton is of type CDebugFile, GetIntance() must return an alias of type CDebugFile, which makes sense. The question now is how to make a singleton which can return instances of a given type. The answer I came up with was to make ISingleton, ISingletonAtFirst and ISingletonAtStart all templates. But this means that I have to derive from templates... something which I have never done and am not sure is possible. Rather than suggest what I think might just work, which will doubtlessly serve only to annoy you, I will rather wait for the profressionals to guide me in the right direction. How do you derive non-templated classes and templated classes from templates? I don''t expect you to write a ten-page explanation, a reference to an article will do great. Thank you greatly for your time. The_Minister 1C3-D3M0N Interactive
[email=mwronen@mweb.co.za" onmouseOver="window.status='Mail The_Minister'; return true" onmouseOut="window.status=' '; return true]The_Minister[/email]1C3-D3M0N Interactive
Just have the instance return an ISingleton pointer. You can then typecast it if necessary.

        class ISingleton{  public:    ISingleton* GetInstance() = 0; // Abstract. Must be defined                                   // in ALL sub-classes...}class ISingletonAtStart : public ISingleton{  public:    ISingleton* GetInstance() {return this;} // Something like this}class ISingletonOneTime : public ISingleton{  public:    ISingleton* GetInstance() {return this;} // Something like this}// Doesn't care what type of ISingleton is passed in...void foo(ISingleton* parm){  ISingleton* NewParm = parm.GetInstance();  // if you are certain you are working with an ISingletonOneTime  // you can typecast it. Generally not a good practice but it   // does work    DoSomething( (ISingletonOneTime*) NewParm );  return;}void DoSomething( ISingletoneOneTime* parm );{  // this really should be a member function of SingletonOneTime  // class.  return;}        


Perhaps simplistic, but if I understand the problem, the solution is simply to apply polymorphism. This works because an ISingletonOneTime and ISingletonAtStart are both ISingletons.



Regards,
Jumpster


Semper Fi

Edited by - Jumpster on October 13, 2000 10:06:50 AM
Regards,JumpsterSemper Fi
Advertisement
Our ideas of singletons differ...

I''ll keep it simple. I neglected to mention that, in addition to this, ISingleton-derived interfaces carry the instance of the singleton within the class. Eg:

    classISingletonAtStart : public ISingleton{   public:      --CLASSTYPE--& GetInstance(); // returns m_Instance   private      static --CLASSTYPE-- m_Instance; // instance of singleton};// initialize (this happens at start, hence ISingletonAtStart// this will be done in the inheriting class''s implementation file// defining the static member causes its contructor to run--CLASSTYPE-- --CLASSTYPE--::m_Instance;    


Where --CLASSTYPE-- is the class type that is inheriting from ISingletonAtStart.

I used ISingletonAtStart for this example, because it appears simpler, but I could just have easily have showed you ISingletonAtFirst. They both have GetInstance(), hence the abstract base interface.

Thus, you could access a singleton as such:
CDebugFile::GetInstance().DoSomething();

Thereby ensuring that there is only one instance of it, and that it is always initialized.

It is important that m_Instance be of --CLASSTYPE--, because the class will have its own constructor (hence, the initialize on start, at first difference).

At this point your method starts becoming less beautiful, simple code, and more of a glorious work-around IMHO, which is indeed humble.

I understand your point, however, but I''m afraid it doesn''t suffice.


The_Minister
1C3-D3M0N Interactive
[email=mwronen@mweb.co.za" onmouseOver="window.status='Mail The_Minister'; return true" onmouseOut="window.status=' '; return true]The_Minister[/email]1C3-D3M0N Interactive
Ok, then it sounds like you are wanting more of a COM style interface inheritance structure...

go to http://msdn.microsoft.com and search for COM Tutorials. There is a tutorial file that demos with code how to do like 20 different things using COM model programming. Look specifically at the tutorial that shows inheritance using Aggregation (i think). The tutorials themselves bite big time, but the code is really neat to follow. Confusing at first but once you get to understanding what it is doing and why, it really becomes quite easy.

I must warn you though, I think COM is actually short for COMplicated. You think my idea was "less beautiful, simple code, and more of a glorious work-around", just wait ''til you see how you do it in COM...


Hope this helps.



Regards,
Jumpster


Semper Fi
Regards,JumpsterSemper Fi
I''m taking a chance here, because I haven''t yet looked at the tutorial but am in the process of doing so, but why can you do it with COM, which is, AFAIK, also C++, but not without it


The_Minister
1C3-D3M0N Interactive
[email=mwronen@mweb.co.za" onmouseOver="window.status='Mail The_Minister'; return true" onmouseOut="window.status=' '; return true]The_Minister[/email]1C3-D3M0N Interactive
That's not saying you have to use COM... just COM methodology.
COM has one thing that makes it work the way you want...

GUIDs: Global Unique Identifiers. Look at the COM model for QueryInterface() and you'll see what I mean. That QueryInterface() along with the Aggregation inheritance is what I was refering to (methodology). Not the fact that you are using the underlying COM Architecture.

ADDED: BTW, Look for COM Samples. Not COM Tutorials. What you will want is in the Workshop section of the web-site.


Regards,
Jumpster


Semper Fi

Edited by - Jumpster on October 13, 2000 11:44:17 AM
Regards,JumpsterSemper Fi
Advertisement
Here is my implementation of my template Singleton class.

        #ifndef _TSINGLETON_H_#define _TSINGLETON_H_template <typename T> class TSingleton  {protected:	static T* s_ptrInstance;protected:	TSingleton() {}public:	virtual ~TSingleton() {}	static T& InstanceRef()	{		if ( s_ptrInstance == NULL )			s_ptrInstance = new T;		return *s_ptrInstance;	}	static T* InstancePtr()	{		if ( s_ptrInstance == NULL )			s_ptrInstance = new T;		return s_ptrInstance;	}};template<typename T>T* TSingleton<T>::s_ptrInstance = NULL;#endif    


Edited by - AlekM on October 13, 2000 1:33:18 PM
The same as mine. Now I need to know how to derive from it. Anyone?

The_Minister
1C3-D3M0N Interactive
[email=mwronen@mweb.co.za" onmouseOver="window.status='Mail The_Minister'; return true" onmouseOut="window.status=' '; return true]The_Minister[/email]1C3-D3M0N Interactive
Here's my derived class for this.

        #ifndef _RESOURCEMANAGER_H_#define _RESOURCEMANAGER_H_#pragma warning ( disable:4786 )#include "stlstring.h"#include "TSingleton.h"#include "UIComponentRecordList.h"#include "BitmapRecordList.h"#include "ImageRecordList.h"class CUIComponetRecord;class CBitmapRecord;class CImageRecord;class CResourceManager;class CResourceManager  : public TSingleton<CResourceManager>{        friend class TSingleton<CResourceManager>;	String m_strWorkingDirectory;	CUIComponentRecordList m_lstComponents;	CBitmapRecordList m_lstBitmaps;	CImageRecordList m_lstImages;	bool m_bCreateOverride;	bool m_bInitialized;private:	CResourceManager();public:	virtual ~CResourceManager();	//Accessors	const String& GetWorkingDirectory() const;	bool GetOverride() const;	//Mutators	void SetWorkingDirectory( String strDirectory );	void SetWorkingDirectory( String& refstrDirectory );	void SetCreateOverride( bool bOverride );	//Methods	void Initialize();	void UnInitialize();	CUIComponentRecord& GetComponentRecord( DWORD dwID );	CUIComponentRecord& GetComponentRecord( String strName );	CBitmapRecord& GetBitmapRecord( DWORD dwID );	CBitmapRecord& GetBitmapRecord( String strName );	CImageRecord& GetImageRecord( DWORD dwID );	CImageRecord& GetImageRecord( String strName );};#define g_ptrRM CResourceManager::InstancePtr()#define g_refRM CResourceManager::InstanceRef()#endif        


Edited by - AlekM on October 13, 2000 1:31:59 PM
    class CFoo : public ISingleton<CFoo>{    ...};    

This topic is closed to new replies.

Advertisement