| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen | 
	
	
		| Autor | Nachricht | 
	
		| Jonathan_Klein Living Legend
 
  
 Alter: 38
 Anmeldedatum: 17.02.2003
 Beiträge: 3433
 Wohnort: Siegerland
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 08.11.2005, 13:21    Titel: Singletons |   |  
				| 
 |  
				| Was ist das? Klassen von den man nur 1 Objekt erstellen kann.
 
 Was soll das?
 Von vielen Klassen braucht man nur ein Objekt. Zum Beispiel eien Klasse die logbücher schreibt oder D3D verwaltet. Mit Singletons muss man nicht globale Objekte erstellen oder an alle Kasse Objektzeiger weitergeben. Außerdem könnte es gar zu Fehlern kommen, wenn zum Beispiel 2 D3D Klassen paralel laufen würden.
 
 Wie geht das?
 Ganz einfach. Du musst nur den/die Konstruktor/Konstruktoren privat machen. In etwa so:
 
  	  | CPP: |  	  | class Logbook {
 public:
 Entry(char* Text);
 private:
 Logbook();
 }
 
 | 
 Dann kannst du keine Objekte mehr erstellen, weil nur die Klasse auf ihren Konstruktor zugriff hat. Dann braucsht du noch ein solche public-Funktion:
 
  	  | CPP: |  	  | static Logbook& Logbook::GetInstance() {
 static Logbook theInstance;
 return theInstance;
 }
 
 | 
 Jetzt kann jede Datei die die "Logbook.h" includiert über folgenden Befehl auf das Logbook zugreifen:
 
  	  | CPP: |  	  | #include "logbook.h" Logbook::GetInstance().Entry("juhu, es klappt!");
 
 | 
 _________________
 https://jonathank.de/games/
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Patrick Dark JLI Master
 
  
 
 Anmeldedatum: 25.10.2004
 Beiträge: 1895
 Wohnort: Düren
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 08.11.2005, 13:38    Titel: |   |  
				| 
 |  
				| Ich glaube viele haben Probleme nur mit nem bissel Code, könntest Du das ggf. mit ner kompletten Header machen und Sourcedatei (ohne D3D, DD, OGL oder DI implementierung). 
 würde dem verständis mehr dienen.
 _________________
 'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
 [ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Dr. Best Senior JLI'ler
 
  
 Alter: 35
 Anmeldedatum: 17.06.2004
 Beiträge: 269
 Wohnort: Köln
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 08.11.2005, 13:50    Titel: |   |  
				| 
 |  
				| Also ich hab noch nie was davon gehört aber es jetzt sofort verstanden. Hört sich ganz praktisch an.
 Ne Performanceverbesserung bringt das aber nicht mit sich oder?
 _________________
 
   Ich bin da, wer noch?
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Jonathan_Klein Living Legend
 
  
 Alter: 38
 Anmeldedatum: 17.02.2003
 Beiträge: 3433
 Wohnort: Siegerland
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 08.11.2005, 13:53    Titel: |   |  
				| 
 |  
				| ^^ Naja, dürfte Speicherplatz sparen, GetInstance könnte man bestimmt auch inline machen, dürfte aber kein Großer Unterschied sein. Da kann man an anderen Stellen mehr optimieren.
 _________________
 https://jonathank.de/games/
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| PeaceKiller JLI Master
 
  
 Alter: 36
 Anmeldedatum: 28.11.2002
 Beiträge: 970
 
 Medaillen: Keine
 
 
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Christian Rousselle Site Admin
 
  
 Alter: 49
 Anmeldedatum: 19.07.2002
 Beiträge: 1630
 
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 20.05.2006, 13:10    Titel: |   |  
				| 
 |  
				| Nachdem ich schon häufiger Probleme mit dem Singleton-Entwurfsmuster hatte, poste ich jetzt mal eine Lösung, die (hoffentlich) mit Visual C++ (6, 7, 7.1, 8) funktioniert. 
  	  | CPP: |  	  | #pragma once 
 template <typename T> class CSingleton
 {
 public:
 
 static T& GetInstance()
 {
 return m_Instance;
 }
 
 static T* GetInstancePtr()
 {
 return &m_Instance;
 }
 
 protected:
 
 CSingleton()
 {
 }
 
 static T m_Instance;
 
 virtual ~CSingleton()
 {
 }
 };
 
 template <typename T> T CSingleton <T>::m_Instance;
 
 | 
 
 Eigentlich ist es schöner, wenn man die statische Variable direck in der GetInstance()-Methode erzeugt:
 
 
  	  | CPP: |  	  | static T& GetInstance() {
 static T m_Instance;
 return m_Instance;
 }
 
 | 
 
 Das macht jedoch mit Visual C++ Probleme (unterschiedliches Verhalten im Debug/Releasemode - scheinbar ist auch nicht wirklich geklärt, wie es sich nach dem Standard korrekt verhalten sollte), deshalb habe ich die oben gezeigte Implementierung gewählt. Außerdem kann man, bei der Lösung mit statischer Variable in der Methode keine GetInstancePtr()-Methode verwenden. Diese Methode gibt es aber nur aus Komfortgründen.
 
 Wenn jetzt eine Singleton-Klasse erzeugt werden soll, z.B. einen ResourceManager, den man typischerweise nur einmal im Programm benötigt, sieht die Definition so aus:
 
  	  | CPP: |  	  | class CResourceManager : public CSingleton<CResourceManager> {
 // ...
 };
 | 
 
 Wenn jemand Probleme damit hat, bitte melden.
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| David Super JLI'ler
 
 
 Alter: 40
 Anmeldedatum: 13.10.2005
 Beiträge: 315
 
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 10.07.2006, 21:52    Titel: |   |  
				| 
 |  
				| Diese Lösung beschränkt sich allerdings auf den Standardkonstruktor der jeweiligen Klasse. Das kann man zwar mehr oder weniger ausbügeln, es ist aber dennoch eine Einschränkung, was nicht gerade schön ist. Außerdem kann man weitere Instanzen aus der abgeleiteten Klasse bilden, was auch gegen den Sinn von Singletons spricht.
 
 Besser wäre etwas wie:
 
 
  	  | CPP: |  	  | template< class T > class TSingleton
 {
 protected:
 static T *m_instance;
 
 public:
 TSingleton()
 {
 assert( !m_instance );
 m_instance = static_cast< T* >( this );
 }
 
 ~TSingleton()
 {
 assert( m_instance );
 m_instance = 0;
 }
 
 static T &GetInstance()
 {
 return *m_instance;
 }
 
 static T *GetInstancePtr()
 {
 return m_instance;
 }
 };
 
 | 
 
 Verwendet würde das folgendermaßen:
 
 
  	  | CPP: |  	  | class Foo : public TSingleton< Foo > {
 private:
 int x;
 
 public:
 static Foo &GetInstance();
 static Foo *GetInstancePtr();
 };
 
 template<> Foo* TSingleton< Foo >::m_instance = 0;
 
 Foo &Foo::GetInstance()
 {
 return *m_instance;
 }
 
 Foo *Foo::GetInstancePtr()
 {
 return m_instance;
 }
 
 #define g_foo Foo::GetInstancePtr()
 
 | 
 
 Nun muss natürlich eine Instanz erzeugt werden. Ansonsten läuft das ganze nicht.
 
 
  	  | CPP: |  	  | int main() {
 Foo bar;
 
 // whatever
 g_foo->whatever( ... )
 
 return 0;
 }
 
 | 
 
 Durch die assert ist sichergestellt das wirklich nur ein Objekt der Klasse existiert. Daher muss der Konstruktor auch nicht protected sein.
 
 grüße
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Otscho Super JLI'ler
 
  
 Alter: 37
 Anmeldedatum: 31.08.2006
 Beiträge: 338
 Wohnort: Gummibären-Gasse
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 12:53    Titel: |   |  
				| 
 |  
				| Wenn ich ein Singleton mache wie,  im ersten Beispiel von Jonathan_Klein, wird dann automatisch eine Instance erzeugt und wird da der Konstruktor und Destruktor aufgerufen ? |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Maxim Senior JLI'ler
 
 
 
 Anmeldedatum: 28.03.2004
 Beiträge: 249
 
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 15:28    Titel: |   |  
				| 
 |  
				| nein, du musst ein mal die instanz erstellen und danach kannst du es überall in dem code verwenden. 
 natürlich kannt du die singleton klasse auch so abändern, dass sie automatisch eine instanz erzeugt, wenn nötig ist, das ist aber keine gute idee, da dann deine singleton-klassen immer einen standardkonstruktor enthalten müssen und das macht ja nicht bei allen klassen sinn.
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Otscho Super JLI'ler
 
  
 Alter: 37
 Anmeldedatum: 31.08.2006
 Beiträge: 338
 Wohnort: Gummibären-Gasse
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 15:55    Titel: |   |  
				| 
 |  
				| Ok ich hab jetzt ein Singlton geschrieben. Nur reagiert es nur wenn es von der Main.cpp angesprochen wird wenn ich von einer anderen Klasse aus versuch seine Funktionen aufzurufen reagiert es überhauptnicht hier mal der Header des Singltons  	  | CPP: |  	  | #ifndef LOGBOOKFILE #define LOGBOOKFILE
 
 #include <windows.h>
 #include <iostream>
 #include <cstdio>
 
 class Logbook
 {
 public:
 static Logbook& Logbook::GetInstance() {
 static Logbook theInstance;
 return theInstance;
 }
 void Init(void);
 void Close(void);
 void Succed(char* location, char* reason);
 void Error(char* location, char* reason);
 void Warning(char* location, char* reason);
 private:
 Logbook();
 virtual ~Logbook();
 FILE *Datei;
 
 };
 
 #endif
 | 
 Und der Zugriff per
  	  | CPP: |  	  | Logbook::GetInstance().Succed(reinterpret_cast<char*>(&"Testarea"), reinterpret_cast<char*>(&"Testreason")); | 
 Weiß jemand was ich falsch mache ?
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Maxim Senior JLI'ler
 
 
 
 Anmeldedatum: 28.03.2004
 Beiträge: 249
 
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 16:13    Titel: |   |  
				| 
 |  
				| was machst du da   
 meine singletonklasse:
 
 
  	  | CPP: |  	  | /******************************************************************** 
 CSingleton.h
 ===========
 Diese Datei ist ein modifizierter Teil der Positron-Gun Engine.
 
 Beschreibung:
 Alle von dieser abgeleitete Klassen konnen nur einmal instanziert werden und
 man bekommt uberall den Zugriff auf diese Klassen ohne irgendwelchen
 Zeiger ubergeben zu mussen.
 Ist sehr pratisch fur Ressourcen-Manager.
 
 Verwendung an Beispiel einer Klasse names A:
 1. Die Klasse A von dieser Klasse ableiten.
 z.B.
 class CTextureManager
 : public Singleton<CTextureManager>
 {
 void GetTexture();
 
 };
 
 2. Eine Instanz von Klasse A irgendwo im Code erstellen.
 z.B. CTextureManager tman;
 
 3. Ab jetzt kann man ueberall auf die Klasse mit A::GetSingleton() zugreifen.
 
 CTextureManager::GetSingleton().GetTexture();
 oder
 CTextureManager::GetSingletonPtr()->GetTexture();
 
 und dass in jedem teil des codes bzw. der cpp datei
 globale Variablen z.B. für TextureManager oder RenderKlasse fallen weg
 
 Zu letzt bearbeitet am:
 25.10.2005
 
 Autor:
 Maxim
 
 ********************************************************************/
 
 #pragma once
 
 #include <cassert>
 
 
 template <typename T>
 class CSingleton
 {
 static T* ms_Singleton;
 
 protected:
 CSingleton(void)
 {
 
 if(!ms_Singleton == 0)
 {
 assert( !ms_Singleton);
 return;
 }
 
 #if defined( _MSC_VER ) && _MSC_VER < 1200
 int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
 ms_Singleton = (T*)((int)this + offset);
 #else
 ms_Singleton = static_cast< T* >( this );
 #endif
 
 }
 
 public:
 ~CSingleton(void)
 {
 assert(ms_Singleton);
 ms_Singleton = 0;
 }
 
 static T& GetSingleton(void)
 {
 assert(ms_Singleton);
 return (*ms_Singleton);
 }
 
 static T* GetSingletonPtr(void)
 {
 assert(ms_Singleton);
 return ms_Singleton;
 }
 };
 
 template <typename T> T*  CSingleton <T>::ms_Singleton = 0;
 | 
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Dragon Super JLI'ler
 
  
 Alter: 39
 Anmeldedatum: 24.05.2004
 Beiträge: 340
 Wohnort: Sachsen
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 17:33    Titel: |   |  
				| 
 |  
				|  	  | Zitat: |  	  | Weiß jemand was ich falsch mache ? | 
 Ja, und so sollte es funktionieren:
 
 
  	  | CPP: |  	  | #ifndef LOGBOOKFILE #define LOGBOOKFILE
 
 #include <windows.h>
 #include <iostream>
 #include <cstdio>
 
 class Logbook
 {
 public:
 static Logbook& GetInstance() // so und nicht anders ;)
 {
 static Logbook theInstance;
 return theInstance;
 }
 void Init(void);
 void Close(void);
 void Succed(const char* location, const char* reason); // nimm lieber const-char
 void Error(const char* location, const char* reason);
 void Warning(const char* location, const char* reason);
 private:
 Logbook();
 virtual ~Logbook();
 FILE *Datei;
 
 };
 
 #endif
 | 
 
 
  	  | CPP: |  	  | // Hier muss nichts gecastet werden! Warum machst du das überhaupt? Logbook::GetInstance().Succed("Testarea", "Testreason");
 | 
 
 Gruß Sven
 _________________
 Nur wenn man ein Ziel sieht, kann man es auch treffen.
 ___________
 Mein Leben, Freunde und die Spieleentwicklung
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| DirectXer Dark JLI'ler
 
  
 
 Anmeldedatum: 05.02.2005
 Beiträge: 1201
 Wohnort: Köln
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 18:27    Titel: |   |  
				| 
 |  
				| ein guter link zum thema singleton ist u.a. dieser hier; da wird eine Singleton-Klasse von Grund auf erzeugt, sodass jeder das Konzept und die "Tricks" verstehen müsste 
 Gruß DXer
 |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Otscho Super JLI'ler
 
  
 Alter: 37
 Anmeldedatum: 31.08.2006
 Beiträge: 338
 Wohnort: Gummibären-Gasse
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 11.06.2007, 19:20    Titel: |   |  
				| 
 |  
				| Danke für eure Tipps. Jetzt gehts
      |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		| Otscho Super JLI'ler
 
  
 Alter: 37
 Anmeldedatum: 31.08.2006
 Beiträge: 338
 Wohnort: Gummibären-Gasse
 Medaillen: Keine
 
 
 | 
			
				|  Verfasst am: 16.04.2009, 08:17    Titel: |   |  
				| 
 |  
				| Besteht auch die Möglichkeit ein Interface für Singletons zu erstellen ? |  | 
	
		| Nach oben |  | 
	
		|  | 
	
		|  |