Singletons



  • Ich verstehe einfach nicht wofür singletons zuständig sind.
    Ich lese mittlerweile im Buch von heiko kalista(C++ für spieleprogrammierung) auf seite 245 von ca. 500 und kriege langsam meine schwierigkeiten bei den fortgeschrittenen themen.

    Meine Frage ist:

    1.Was ist die Aufgabe von Singletons.
    2.Wie wendet man sie sinvoll an.
    3.Und warum gibt es sie überhaupt?

    Ich wäre euch wirklich dankbar wenn ihr mir weiterhelfen könntet,
    bin bis jetzt immer einigermaßen mit dem Lernen von C++ klar gekommen und hoffe
    das es jetzt nicht daran happert.

    Vielen Dank 🙂



  • jooker schrieb:

    1.Was ist die Aufgabe von Singletons.

    Im Prinzip globale Variablen. Nur allgemeiner, man kann Zusatztricks einbauen. Meistens daß sie erst enstehen, wenn man sie zum ersten mal benutzt. Oder daß sie wegen unklarer Zerstörungsreihenfolge nochmal wiederauferstehen können, obwohl sie eigentlich schon weg waren.

    2.Wie wendet man sie sinvoll an.
    

    Klassisches Beispiel ist wohl sowas wie ein Standarddrucker, der aber erst entstehen soll, wenn der Benutzer tatsächlich mal was drucken will, dann aber bis zum Programmende leben soll, falls er nochmal was drucken will.

    3.Und warum gibt es sie überhaupt?
    

    Sie können halt ein wenig mehr.



  • Singletons "gibt" es nicht, das ist einfach ein abstraktes Konzept und nicht etwa Teil der Sprache.
    Ein Singleton ist eine Klasse, von der man nur eine einzige Instanz im ganzen Programm benötigt (mit privatem Konstruktor und einer statischen Memberfunktion getInstance() geht man dann meist sicher, dass wirklich nur eine Instanz erzeugt werden kann). Dementsprechend kann die Aufgabe eines Singletons alles mögliche sein.

    Beispiel: du hast eine Datenbank und eine Klasse, die das Interface zu dieser Datenbank darstellt - davon brauchst du nur eine Instanz => Singleton.
    Oder du hast eine Benutzerverwaltung und eine Klasse, die sämtliche Accounts verwaltet: auch ein Fall für ein Singleton.



  • volkard schrieb:

    jooker schrieb:

    1.Was ist die Aufgabe von Singletons.

    Im Prinzip globale Variablen. Nur allgemeiner, man kann Zusatztricks einbauen. Meistens daß sie erst enstehen, wenn man sie zum ersten mal benutzt. Oder daß sie wegen unklarer Zerstörungsreihenfolge nochmal wiederauferstehen können, obwohl sie eigentlich schon weg waren.

    2.Wie wendet man sie sinvoll an.
    

    Klassisches Beispiel ist wohl sowas wie ein Standarddrucker, der aber erst entstehen soll, wenn der Benutzer tatsächlich mal was drucken will, dann aber bis zum Programmende leben soll, falls er nochmal was drucken will.

    Den Sinn von Singleton hast du nicht kapiert. Die Lebensdauer ist es nicht. Das was Nanyuki schreint passt schon besser.



  • Du hast unter Umständen eventuell den wichtigsten Satz "Im Prinzip globale Variablen." nicht lange genug behalten. Darin ist bereits enthalten, daß es sie nur einmal gibt. Zwischen der einen Datenbank-Connection und dem einen Standarddrucker sehe ich auch keinen Unterschied. Privaten Konstruktor und getInstance habe ich nicht gefordert, weil sie für Singletons nicht so nötig sind. Die Lebensdauer, insbesondere die Initialisierungsreihenfolge und lazy sein, ist es nicht immer, aber meistens, die einen dazu führt, Sachen wie die Benutzerverwaltung zum Singleton zu machen, statt zur schlichten globalen Variablen.



  • Das gibt dem ganzen auch nicht mehr Sinn. Dein Standarddrucker Beispiel zeigt doch, dass du es nicht verstanden hast. Warum soll der ein Singleton sein? Ganz sicher nicht dazu, dass er ewig im Speicher bleibt. Je nach dem was man vor hat könnte das Ding wo man den Standarddrucker bekommt ein Singleton sein. Wenn einer den Standarddrucker ändert, während er verwendet wird, was passiert dann? Programmcrash?



  • Hast zwar deine Antwort inzwischen erweitert, aber meine passt immer noch so.



  • Danke,
    so langsam verstehe ich das.

    Aber Das thema singelton ist dann ja anscheinend wie Nanyuki schon mit der zeile:
    "Singletons "gibt" es nicht, das ist einfach ein abstraktes Konzept und nicht etwa Teil der Sprache." sagte eher unwichtig und kann vernachlässigt werden oder?



  • Vernachlässigen würde ich es nicht, gibt gute Einsatzgebiete und man solte es zumindest kennen, schon allein deshalbw eil einem so eine Kosntruktion durchaus mal über den Weg laufen kann.



  • #ifndef TSINGLETON
    #define TSINGLETON

    template <class T>
    class TSingleton
    {
    protected:

    // Membervariablen
    static T *m_pSingleton; // Statisches Objekt

    public:

    // Memberfunktionen

    // Destruktor
    //
    virtual ~TSingleton ()
    {
    }

    // Get
    //
    // Aufgabe: Wenn nötig, statisches Objekt erzeugen und
    // Zeiger darauf zurückgeben
    //
    inline static T* Get ()
    {
    // Existiert schon eine Instanz?
    if (!m_pSingleton)
    m_pSingleton = new T; // Nein, dann neue Instanz erzeugen

    // Zeiger auf die Instanz zurückgeben
    return (m_pSingleton);

    } // Get

    // Statisches Objekt freigeben
    //
    static void Del ()
    {
    // Gab es eine Instanz?
    if (m_pSingleton)
    {
    delete (m_pSingleton); // Ja, dann freigeben
    m_pSingleton = NULL; // und Zeiger auf NULL setzen
    }

    } // Del

    };

    // Die statische Variable erzeugen
    //
    template <class T>
    T* TSingleton<T>::m_pSingleton = 0;

    #endif

    Das ist ein kleines Beispiel aus dem Buch.

    Warum schrieb der Autor in den ersten zeilen:
    #ifndef TSINGLETON
    #define TSINGLETON

    und zum schluss:
    #endif

    Vielleicht könnte jemand sich nochmal auf das beispiel beziehn,
    wäre euch sehr verbunden,mit beispielen lernt man es besser 😉



  • jooker schrieb:

    Das ist ein kleines Beispiel aus dem Buch.

    Warum schrieb der Autor in den ersten zeilen:
    #ifndef TSINGLETON
    #define TSINGLETON

    und zum schluss:
    #endif

    Die Dinger nennen sich Include Guards

    Die Implementierung is allerdings etwas seltsam. Der Konstruktor (& Copy c'tor) sind öffentlich. Der Destruktor könnte auch protected gemacht werden, dann kann man sich "virtuellen" Overhead sparen.
    Get sollte lieber eine Referenz zurückgeben und könnte z.B. auch als Mayers-Singleton implementiert werden (das spart dir diese if-Abfrage). Bei Del ist die if-Anweisung unnötig. Uswusf...



  • Also ich nutze imer diese Variante, die finde ich Persönlich besser.

    class Singleton
    {
    private:
        CTor;
        Copy-CTor;
        Operator=;
    private:
        DTor;
        static Singleton& getInstance()
        {
            static Singleton single;
            return single;
        };
    };
    

    Wobei das dann auch kein Template ist sondern in der Klasse direkt integriert.



  • Also haben die Singeltons im Grunde nur ein vorteil:
    Sie schaffen Ordnung und übersichtlichkeit da man seperat eine Singleton klasse in einer hpp datei speichern kann von wo aus sich einfach eine Instanz erzeugen lässt welche an die cpp Datei übergeben werden kann.

    ich hoffe ich hab es jetzt abschließend richtig erklärt,
    wenn ich was vergessen hab zu erwähnen,sagt es mir bitte.



  • Das is schonmal Nah dran aber immernoch daneben. Durch die Singletons braucht man garkeine globale Variable mehr, man erstellt sie als Normale Klasse, zB ein TexturManager, und jeder der was daran machen will kann sich über getInstance eine Referenz auf die Instanz holen, somit braucht man keine globale Variable mehr.



  • jooker schrieb:

    Also haben die Singeltons im Grunde nur ein vorteil:

    Du meinst einen.

    ich hoffe ich hab es jetzt abschließend richtig erklärt

    Nein. Von Singletons kann es nur eine einzige Instanz geben, wie es der Name auch schon nahelegt. Das ist sein Zweck.



  • Xebov schrieb:

    Durch die Singletons braucht man garkeine globale Variable mehr

    "Global" im formalen Sinne von C++ vielleicht nicht.

    Wenn man unter "global" jedoch das Konzept versteht, Zugriff von überall her direkt zu ermöglichen, gehören Singletons sehr wohl dazu (wie auch schon erwähnt wurde).



  • Xebov schrieb:

    [...] somit braucht man keine globale Variable mehr.

    Was ist mit globalen Referenzen? Sowas lässt sich nicht mit einem Singleton realisieren.



  • Nexus schrieb:

    Wenn man unter "global" jedoch das Konzept versteht, Zugriff von überall her direkt zu ermöglichen, gehören Singletons sehr wohl dazu (wie auch schon erwähnt wurde).

    OK, das is dann wieder sone Auslegungssache wie mans versteht.

    David_pb schrieb:

    Was ist mit globalen Referenzen? Sowas lässt sich nicht mit einem Singleton realisieren.

    Ich evrstehe nicht ganz worauf du hinaus willst? Ich bezog mich darauf das ich mit der Singleton keine globale Variable mehr brauche da der Zugriff von überall ja möglich ist. Das man Singletons nicht für jede Kleinigkeit einsetzt setze ich jetzt einfach mal voraus.



  • David_pb schrieb:

    Was ist mit globalen Referenzen? Sowas lässt sich nicht mit einem Singleton realisieren.

    Was meinst du mit globaler Referenz?

    So etwa ?

    SingletonType& a = SingletonType::getInstance();
    

    Is zwar nicht möglich,
    aber getInstance sollte ja eine Referenz zurückgegeben ( und keinen Zeiger),
    daher hat sich das in meinen Augen schon eliminiert.

    Oder hab ich dich falsch verstanden ?



  • Xebov schrieb:

    Also ich nutze imer diese Variante, die finde ich Persönlich besser.

    class Singleton
    {
    private:
        CTor;
        Copy-CTor;
        Operator=;
    private:
        DTor;
        static Singleton& getInstance()
        {
            static Singleton single;
            return single;
        };
    };
    

    Wobei das dann auch kein Template ist sondern in der Klasse direkt integriert.

    find ich zwar eigtl auch toll, aber dummerweise kann man die zerstörungs-reihenfolge eben nicht festlegen : <

    bb


Log in to reply