SingleTon Klasse



  • Objektinstanz dynamisch auf dem Heap anlegen:

    class Client 
    { 
       private: 
         // Standard- und Copykonstruktor sind private. 
         // Nur Methoden dieser Klasse können auf sie zugreifen.
         Client() {}
         Client( const Client& );
    
         // Dekonstruktor
         ~Client(); 
    
         // Ein Zeiger auf die einzige Instanz
         static Client *m_instanz;
    
       public: 
         // Diese statische Methode erzeugt die einzige Instanz.
         // Nur über diese Methode erhalten Anwender den Zugriff auf
         // die Instanz.
         static Client* getInstance();
    
         static void deleteClient() { delete m_instanz; };  
    }; 
    
    Client* Client::m_instanz = 0; 
    
    Client* Client::getInstance() 
    { 
      // Die Instanz wird erst beim ersten Aufruf erzeugt.
      if( m_instanz == 0 ) 
          m_instanz = new Client(); 
      return m_instanz; 
    }
    
    static void Client::deleteClient();
    

    Objektinstanz statisch anlegen:

    class Client
    {
       // Standard- und Copykonstruktor sind private. 
       // Nur Methoden dieser Klasse können auf sie zugreifen.
       private:
         Client() {}
         Client( const Client& );
    
       public:
         // Diese statische Methode erzeugt die einzige Instanz.
         // Nur über diese Methode erhalten Anwender den Zugriff auf
         // die Instanz.
         static Client& getInstance();
    };
    
    Client& Client::getInstance()
    {
      // Die Instanz wird erst beim ersten Aufruf erzeugt.
      // Endet das Programm, wird Instanz vernichtet.
      static Client m_instanz;
      return m_instanz;
    }
    

    wenn ich eine Objektinstanz dynamisch auf dem Heap anlege (siehe bsp 1) dann muss der benutzer das delete selber aufrufen? was hat der dekonstruktor dann zu tun?
    beispiel 2 müsste so ok sein?

    cu 😃



  • SideWinder schrieb:

    Das was vorher da stand war viel netter Shlo.

    Ja, fand ich auch 😉



  • Ensure a class
    only has one instance, and provide a global point of access to it...

    Therefore, you should use Singleton when you model types that conceptually have a unique instance in the application, such as Keyboard, Display, PrintManager, and SystemClock. Being able to instantiate these types more than once is unnatural at best, and often dangerous

    diese beiden textstellen ließen eigentlich auch meine klasse als singleton zu.

    sie sagen eigentlich nur, dass ein singleton alles ist was verhindert, dass von einer Klasse 2 instanzen existieren. mein singleton ließe auch nur eine instanz des "SystemClock" objekts zu.

    Den globaln Accesspoint stellt dann die Klasse Singleton selber über den ctor und dem operator ->. Imho wird es wohl auch praktisch keinen unterschied machen, wenn man einen ctor anstatt einen statischen instance aufzurufen(bei inlinecode wird der compiler in beiden fällen hoffentlich das gleiche draus machen).

    und selbst wenn ihr mir klar machen würdet, dass mein beispiel kein singleton darstellt, aus dem einen grund,dass der rumpf mehrfach existieren kann, so würde ich den ansatz weiterverfolgen, da er einige probleme die singletons haben einfach nicht hat :). nur würde ich mich fragen, was das effektiv ist, was ich mir da zusammengeschustert hab 😮

    ps: nur weil mich das mal aus compiler verstehtechnischen gründen in dem zusammenhang interessiert: verbraucht eine instanz einer klasse ohne nicht statischen variablen platz im speicher?



  • kann jemand meine frage auf page 5 letzter post beantworten?

    cu



  • sie sagen eigentlich nur, dass ein singleton alles ist was verhindert, dass von
    einer Klasse 2 instanzen existieren. mein singleton ließe auch nur eine instanz
    des "SystemClock" objekts zu.

    Code von interpreter:

    Singleton<int> s1, s2, s3, s4;
    

    Das sind fuer mich 4 Instanzen dieser Klasse. Du verhinderst, dass mehrmals
    Speicher fuer objectPointer reserviert wird, aber du verhinderst ganz und gar
    nicht, dass ich mehrere Instanzen deiner Klasse Singleton<T> erstellt
    werden kann.

    ps: nur weil mich das mal aus compiler verstehtechnischen gründen in dem zusammenhang interessiert: verbraucht eine instanz einer klasse ohne nicht statischen variablen platz im speicher?

    Ich wuerde sagen schon. Wie andere Variablen, besitzt auch eine Instanz einer
    Klasse einen Speicherbereich.

    mfg
    v R



  • was hat der dekonstruktor dann zu tun?

    Der DTor bei der ersten Variante waere noetig, falls du irgendwelche Member hast,
    die dynamisch erstellt worden sind.

    beispiel 2 müsste so ok sein?

    Ja ist es.

    mfg
    v R



  • Das sind fuer mich 4 Instanzen dieser Klasse. Du verhinderst, dass mehrmals
    Speicher fuer objectPointer reserviert wird, aber du verhinderst ganz und gar
    nicht, dass ich mehrere Instanzen deiner Klasse Singleton<T> erstellt
    werden kann.

    hab ich auch nie behaupted. ich sagte dem sinn nach eher was von "T existiert nur einmal"

    Ich wuerde sagen schon. Wie andere Variablen, besitzt auch eine Instanz einer
    Klasse einen Speicherbereich.

    das stimmt, aber normalerweise haben variablen ja auch eine größe, einen int hat(um flames vorzubeugen:normalerweise) 32 bits, der speiechrbereich der variablen im speicher ist 32 bits groß.

    meine klasse hat o bits als platz für sich beansprucht. wird im speicher nun ein 0 bit großer speicehrbereich angelegt,oder mehr? Oder ist der compiler schlau genug, um zu merken, dass er sich hier nicht diese arbeit machen muss?



  • otze schrieb:

    Das sind fuer mich 4 Instanzen dieser Klasse. Du verhinderst, dass mehrmals
    Speicher fuer objectPointer reserviert wird, aber du verhinderst ganz und gar
    nicht, dass ich mehrere Instanzen deiner Klasse Singleton<T> erstellt
    werden kann.

    hab ich auch nie behaupted. ich sagte dem sinn nach eher was von "T existiert nur einmal"

    Beim Singleton redet man von Instanz der Klasse, nicht von Instanz der Member.

    otze schrieb:

    Ich wuerde sagen schon. Wie andere Variablen, besitzt auch eine Instanz einer
    Klasse einen Speicherbereich.

    das stimmt, aber normalerweise haben variablen ja auch eine größe, einen int hat(um flames vorzubeugen:normalerweise) 32 bits, der speiechrbereich der variablen im speicher ist 32 bits groß.

    meine klasse hat o bits als platz für sich beansprucht. wird im speicher nun ein 0 bit großer speicehrbereich angelegt,oder mehr? Oder ist der compiler schlau genug, um zu merken, dass er sich hier nicht diese arbeit machen muss?

    Ich meine mich an einen Thread hier erinnern zu koennen, wo jemand das
    angesprochen hatte. Ich denke der Compiler wird hier mindestens 1 Byte Speicher
    reservieren, welcher das Objekt repraesentiert. Schlau wird der Compiler wohl
    auf jeden Fall sein. Ob es dazu etwas im Standard gibt weiss ich nicht, aber
    ich werde mal den Draft durchsuchen.

    mfg
    v R



  • net schrieb:

    DEvent schrieb:

    ...
            static void createSingelton(/*Paramter die zum erstellen gut sind*/)
            { singelton = new Singelton(/*Paramter die zum erstellen gut sind*/);
            }
    ...
    

    musst aber noch verhindern, dass 'createSingleton' mehrfach aufgerufen wird. sonst hat man doch mehrere instanzen

    wieso das? ein programmierer sollte schon wissen was er macht ...
    die regel ist doch ganz einfach: rufe in deiner main funktion einmal createSingelton() auf und am ende dann deleteSingelton. viele APIs haben auch solche einfache regel, wenn man sich nicht drann hält selbst schuld. ( z.b. winapi mit getDC() releaseDC(), oder D3DX mit BeginScene() EndScene() )
    aber man könnte ja auch machen

    void createSingelton()
    {
        if ( sengelton ) return;
        singelton = new Singelton();
    }
    

    natürlich kann man an der implementierung von singelton rumtricksen aber das prinzip bleibt das gleiche



  • @virtuell Realisticer:
    dann brauch ich in der klasse kein

    ~Client();
    

    hab ich das richtig verstanden?

    cu



  • otze schrieb:

    DEvent schrieb:

    sovie text für das singelton muster 😮
    dabei ist es das einfachste muster überhaupt
    ich mach immer:

    class Singelton
    {
        private:
            static Singelton* singelton;
            Singelton(/*Paramter die zum erstellen gut sind*/);
            ~Singelton();
        public:
            static Singelton* getSingelon() { return singelton; };
            static void createSingelton(/*Paramter die zum erstellen gut sind*/)
            { singelton = new Singelton(/*Paramter die zum erstellen gut sind*/);
            }
            static void deleteSongelton() { delete singelton; };
    };
    

    mehr braucht man doch net

    ...
    der weitere punkt ist der: statische variablen+statische funktionen!=Singleton
    ...

    😕 😕
    statische variablen+statische funktionen Singleton



  • nein, macht aber auch nichts den drin zu haben 😉



  • oop schrieb:

    @virtuell Realisticer:
    dann brauch ich in der klasse kein

    ~Client();
    

    hab ich das richtig verstanden?

    cu

    Ja, das ist korrekt. In deiner Klasse gibt es nichts, was du per Hand wieder
    loeschen musst. Haettest du z. B. sowas: (stark gekuerzt)

    MyClass() {
       foo = new bar[100];
    }
    

    dann saehe das wieder anders aus, da du dich dann darum kuemmern muesstet,
    den Speicherbereich den foo belegt wieder freizugeben. Hier muesstest du dann
    einen DTor definieren.

    In deinem Beispiel oben ist das nicht noetig.

    mfg
    v R



  • DEvent schrieb:

    net schrieb:

    DEvent schrieb:

    ...
            static void createSingelton(/*Paramter die zum erstellen gut sind*/)
            { singelton = new Singelton(/*Paramter die zum erstellen gut sind*/);
            }
    ...
    

    musst aber noch verhindern, dass 'createSingleton' mehrfach aufgerufen wird. sonst hat man doch mehrere instanzen

    wieso das? ein programmierer sollte schon wissen was er macht ...
    die regel ist doch ganz einfach: rufe in deiner main funktion einmal createSingelton() auf und am ende dann deleteSingelton. viele APIs haben auch solche einfache regel, wenn man sich nicht drann hält selbst schuld. ( z.b. winapi mit getDC() releaseDC(), oder D3DX mit BeginScene() EndScene() )
    aber man könnte ja auch machen

    void createSingelton()
    {
        if ( sengelton ) return;
        singelton = new Singelton();
    }
    

    natürlich kann man an der implementierung von singelton rumtricksen aber das prinzip bleibt das gleiche

    Du kannst das gerne so machen, aber warum das einfache Prinzip des Singleton
    so verkomplizieren? Warum es dem Programmierer nicht einfach machen, deine
    Klassen zu benutzen?

    statische variablen+statische funktionen ≡ Singleton

    Das ist natuerlich quatsch. Singletons koennen ohne weiteres nonstatic Member
    haben.

    mfg
    v R



  • ps: nur weil mich das mal aus compiler verstehtechnischen gründen in dem
    zusammenhang interessiert: verbraucht eine instanz einer klasse ohne nicht
    statischen variablen platz im speicher?

    Ich habe im Draft mal nachgeschaut, aber diesbezueglich nichts gefunden, was ja
    eigentlich nicht verwunderlich war, da diese Details besser dem Compilerbauer
    ueberlassen werden.

    mfg
    v R



  • DEvent schrieb:

    net schrieb:

    musst aber noch verhindern, dass 'createSingleton' mehrfach aufgerufen wird. sonst hat man doch mehrere instanzen

    wieso das? ein programmierer sollte schon wissen was er macht ...

    naja. ich finde es aber schon besser, wenn sich die klassen gegen fehlbedienung selber schützen.

    DEvent schrieb:

    aber man könnte ja auch machen

    void createSingelton()
    {
        if ( sengelton ) return;
        singelton = new Singelton();
    }
    

    das ist schon besser. jetzt packst du das noch in deine 'getInstance'-methode und dann ist es sogar benutzerfreundlich. 😉



  • virtuell Realisticer schrieb:

    oop schrieb:

    @virtuell Realisticer:
    dann brauch ich in der klasse kein

    ~Client();
    

    hab ich das richtig verstanden?

    cu

    Ja, das ist korrekt. In deiner Klasse gibt es nichts, was du per Hand wieder
    loeschen musst. Haettest du z. B. sowas: (stark gekuerzt)

    MyClass() {
       foo = new bar[100];
    }
    

    dann saehe das wieder anders aus, da du dich dann darum kuemmern muesstet,
    den Speicherbereich den foo belegt wieder freizugeben. Hier muesstest du dann
    einen DTor definieren.

    In deinem Beispiel oben ist das nicht noetig.

    mfg
    v R

    class Client 
    { 
       private: 
         // Standard- und Copykonstruktor sind private. 
         // Nur Methoden dieser Klasse können auf sie zugreifen. 
         Client() {} 
         Client( const Client& ); 
    
         // Dekonstruktor 
         //~Client(); 
    
         // Ein Zeiger auf die einzige Instanz 
         static Client *m_instanz; 
    
       public: 
         // Diese statische Methode erzeugt die einzige Instanz. 
         // Nur über diese Methode erhalten Anwender den Zugriff auf 
         // die Instanz. 
         static Client* getInstance(); 
    
         static void deleteClient() { delete m_instanz; };   
    }; 
    
    Client* Client::m_instanz = 0; 
    
    Client* Client::getInstance() 
    { 
      // Die Instanz wird erst beim ersten Aufruf erzeugt. 
      if( m_instanz == 0 ) 
          m_instanz = new Client(); 
      return m_instanz; 
    } 
    
    static void Client::deleteClient();
    

    warum soll da der dekonstruktor raus? hast dich glaubi verschaut... ich lösch da mit der delete methode...das objekt...könnte das nicht alles der dekonstruktur machen?
    zb:

    ~Client() { delete m_instanz; };
    

    verstehst mich? die frage is halt nur...was ist wenn kein objekt erstellt wurde...dann gibs nen crash mit dem dekontruktor oder?

    cu



  • 9/3
    complete objects and member subobjects of class type shall have nonzero size.
    außerdem muss jedes objekt eine eigene adresse haben (was heißt mindestens 1 byte (char) platz).
    kannst ja einmal durch ein array durchlaufen

    struct Empty {
    	void print () {
    		cout << "address: " << (void*)this << endl;
    	}
    };
    
    int main () {	
    	Empty e[10];
    	for_each (e, e+sizeof(e)/sizeof(*e), mem_fun_ref(&Empty::print));
    }
    


  • die frage is halt nur...was ist wenn kein objekt erstellt wurde...dann gibs nen
    crash mit dem dekontruktor oder?

    Du hast aber gar keinen Zugriff auf das Objekt. Du bist auf die statische
    delete-Memberfunktion gebunden. Fuer m_instanz zu loeschen nutzt dir der DTor
    gar nichts, da er nie aufgerufen wird. Er wird erst in dem Moment aufgerufen,
    wenn du 'delete m_instanz;' ausfuehrst.

    @davie
    Super und ich suche, suche und suche...es naechste mal frage ich dich gleich 😃

    mfg
    v R



  • Hi!

    delete kann auch aufgerufen werden, wenn das Objekt auf 0 zeigt, da passiert gar nichts. Wenn kein Objekt erstellt werden konnte, bzw. zu wenig Speicher vorhanden ist um eine Instanz anzulegen, dann wirft new eine Exeption.

    Du brauchst deleteClient nicht nochmal hinschreiben wenn es bereits definiert ist:

    static void Client::deleteClient();
    

    Kannst also die letzte Zeile streichen oder dort die definition hinpacken.

    Code-Hacker


Anmelden zum Antworten