JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=e14c690601c0c9e528ec8cf6c10117eeMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Singletons
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Jonathan_Klein
Living Legend


Alter: 36
Anmeldedatum: 17.02.2003
Beiträge: 3431
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 08.11.2005, 14:21    Titel: Singletons Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 08.11.2005, 14:38    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Dr. Best
Senior JLI'ler


Alter: 34
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 08.11.2005, 14:50    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
Jonathan_Klein
Living Legend


Alter: 36
Anmeldedatum: 17.02.2003
Beiträge: 3431
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 08.11.2005, 14:53    Titel: Antworten mit Zitat

^^
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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
PeaceKiller
JLI Master


Alter: 35
Anmeldedatum: 28.11.2002
Beiträge: 970

Medaillen: Keine

BeitragVerfasst am: 08.11.2005, 15:29    Titel: Antworten mit Zitat

Eine gute Implementierung:
http://cvs.sourceforge.net/viewcvs.py/ogre/ogrenew/OgreMain/include/OgreSingleton.h?view=markup

Deklariert wird ein Singelton so:
CPP:
class KLASSE : public Ogre::Singleton<KLASSE>


und dann muss man ihn nur noch instanzieren mit:
CPP:
template<> KLASSE* Singleton<KLASSE>::ms_Singleton = 0;


edit:
Das Orginal:
http://www.drizzle.com/~scottb/publish/gpgems1_singleton.htm
_________________
»If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.«
– Robert X. Cringely, InfoWorld magazine
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Christian Rousselle
Site Admin


Alter: 47
Anmeldedatum: 19.07.2002
Beiträge: 1630

Medaillen: Keine

BeitragVerfasst am: 20.05.2006, 14:10    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
David
Super JLI'ler


Alter: 39
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 10.07.2006, 22:52    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Otscho
Super JLI'ler


Alter: 35
Anmeldedatum: 31.08.2006
Beiträge: 338
Wohnort: Gummibären-Gasse
Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 13:53    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Maxim
Senior JLI'ler



Anmeldedatum: 28.03.2004
Beiträge: 249

Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 16:28    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Otscho
Super JLI'ler


Alter: 35
Anmeldedatum: 31.08.2006
Beiträge: 338
Wohnort: Gummibären-Gasse
Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 16:55    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Maxim
Senior JLI'ler



Anmeldedatum: 28.03.2004
Beiträge: 249

Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 17:13    Titel: Antworten mit Zitat

was machst du da Shocked

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
Benutzer-Profile anzeigen Private Nachricht senden
Dragon
Super JLI'ler


Alter: 37
Anmeldedatum: 24.05.2004
Beiträge: 340
Wohnort: Sachsen
Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 18:33    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 19:27    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Otscho
Super JLI'ler


Alter: 35
Anmeldedatum: 31.08.2006
Beiträge: 338
Wohnort: Gummibären-Gasse
Medaillen: Keine

BeitragVerfasst am: 11.06.2007, 20:20    Titel: Antworten mit Zitat

Danke für eure Tipps.
Jetzt gehts Very Happy Laughing Very Happy
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Otscho
Super JLI'ler


Alter: 35
Anmeldedatum: 31.08.2006
Beiträge: 338
Wohnort: Gummibären-Gasse
Medaillen: Keine

BeitragVerfasst am: 16.04.2009, 09:17    Titel: Antworten mit Zitat

Besteht auch die Möglichkeit ein Interface für Singletons zu erstellen ?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum