Mechanismus zum Umgehen eines Singletons !



  • Hey Leute ich hab da mal wieder eine Frage ...
    Unsere Aufgabe war es eine Klasse so abzusichern dass man sie standard mäßig nur einmal instanzieren kann ..
    Ich hab dies über ein Singleton realisiert.
    1.)Konstruktor auf privat
    2.)getinstance Funktion geschrieben die eine Referenz auf ein
    Objekt einer Klasse zurück gibt ..

    Einzelkind* Einzelkind::getinstance()
    {
         cout << "\nG E T  I N S T A N C E ";
    	 if(!instance) instance = new Einzelkind;
    	 return instance;
    }
    

    So nun sollen wir allerdinsg einen Mechanismus schaffen mit dem man das ganze umgehen kann , also trotz alle dem eine Instanz zu erzeugen .

    Ich komm einfach nich drauf wie ich das machen kann...

    Ich bräuchte erstmal nur einen kleinen tip , bzw ein Stichwort welches mich auf den richtigen Weg führt ..

    Danke



  • Was soll der denn umgehen?



  • Geht nur mit Mitteln, die nicht vom Standard abgedeckt sind, wie

    #define private public
    

    oder Adressenraten, reinterpret_cast, memcpy und dergleichen.

    Ich würd's mit Adressenraten machen. Leg Dir eine globale Variable an. Du benutzt Einzelkind und Einzelkind benutzt cout. Vermutlich liegt Enzelkond::instance zwischen cout und Deiner globalen Variablen im Speicher. Lauf von Deiner globalen Variablen runter bis nach cout und such nach einem Zeiger, der gleich instance ist. Das löst höchst wahrscheinlich keine Schutzverletzung aus. Schreibe eine 0 rein und hol Dir ein zweites EInzelking mit getinstance.

    Auf was will der Prof hinaus?



  • Ja seine Frage lautet so :

    2. Aufgabe (Abgabe!)
    Bei einer Reihe von Anwendungen ist es wichtig sicherzustellen, dass von einer bestimmten Klasse
    höchstens eine Instanz existiert. (Beispiele: Klassen, die zustandsgebundene Protokolle mit
    peripheren Komponenten abwickeln, oder Klassen, die bestimmte Betriebssystem-Ressourcen
    managen).
    Entwickeln Sie eine Klasse Einzelkind, die a) instanziierbar ist und b) garantiert höchstens einmal
    instanziiert wird. Verhindern Sie, dass mehrere Instanzen, z.B. mittels
    
    Einzelkind e1;
    Einzelkind e2;
    Einzelkind e3 = e1;
    
    angelegt werden und schaffen Sie einen Mechanismus, trotzdem eine Instanz zu erzeugen.
    Hinweis: Geben Sie zur Prüfung im Destruktor irgendeinen String aus. Erscheint der String mehrfach,
    haben Sie etwas übersehen.
    


  • Bacid90210 schrieb:

    Ja seine Frage lautet so :

    angelegt werden und schaffen Sie einen Mechanismus, trotzdem eine Instanz zu erzeugen.
    

    Das ist doch einfach das getinstance. Bist fertig. Du solltest nie den Singleton aushebeln.



  • Aber Du müßtest noch machen, daß sich das Einzelkind auch automatisch löscht.
    Am hübschesten als static-Variable in getinstance. Er wollte im Destruktor die Ausgabe.



  • Ja aber heisst es nicht

    : Verhindern sie das man mehrere Instanzen erzeugen kann
    und schaffen sie einen Mechanismus trotzdem eine anzulegen .
    :-S oder versteh ich die Frage iwie falsch ...

    Im Destruktor will er ja nur einen String ausgegeben haben
    ...mehr nich . Hab ich auch schon erledigt 😃 .

    Bin mir jetz aber nicht sicher ob ich den Singleton noch aushebeln soll oder nicht ...ich schreib im am besten mal neh Mail .



  • Das verstehe ich als

    : Verhindern sie das man mehr als eine Instanze erzeugen kann
    und schaffen sie einen Mechanismus trotzdem eine einzige anzulegen .



  • ich hab ihm jetzt erstmal geschrieben ...
    Mal sehen was er schreibt ...

    Werd euch morgen informieren .

    good n8t. 😃



  • Entwickeln Sie eine Klasse Einzelkind, die a) instanziierbar ist und b) garantiert höchstens einmal
    instanziiert wird.

    Ich hätte das so verstanden, dass die Klassen einen - public - ctor haben muss. Obwohl ich die Anforderung etwas komisch finde. Allerdings finde ich die Formulierung der Aufgabenstellung so oder so schlecht, da mir nicht 100% klar wäre, was der nun haben will.

    Ich hätte vermutlich sowas in der Art abgegeben:

    class Foo
    {
    public:
        Foo()
        {
            if (sm_instanceCount != 0)
                throw std::logic_error("sicher nicht!");
    
            // ...
    
            sm_instanceCount = 1;
        }
    
        // ...
    
    private:
        static int sm_instanceCount;
    };
    


  • Eine weitere Lösung wäre noch, mittels PIMPL das eigentliche Objekt in einen static-Member-Pointer auszulagern. Dieser zählt Referenzen mit.
    Aber im Prinzip ist das auch ein Singleton, nur etwas versteckt...
    Man kann halt dann sowas machen:

    Einzelkind e1;
    Einzelkind e2;
    

    Und beide Einzelkinder sind dann identisch. Wobei mir der letzte Satz nicht gefällt 😛



  • l'abra d'or schrieb:

    Einzelkind e1;
    Einzelkind e2;
    

    Und beide Einzelkinder sind dann identisch.

    Warum sollte man sowas tuen wollen? Wenn ich ein Singleton habe und nur mit einem Objekt arbeiten muss/brauch, warum sollte ich dann mit mehreren Einzelkinder rumhantieren wollen, wenn es im Endeffekt doch das gleiche ist. Wäre das nicht unnötige Verwirrung?



  • FreakY<3Cpp schrieb:

    l'abra d'or schrieb:

    Einzelkind e1;
    Einzelkind e2;
    

    Und beide Einzelkinder sind dann identisch.

    Warum sollte man sowas tuen wollen? Wenn ich ein Singleton habe und nur mit einem Objekt arbeiten muss/brauch, warum sollte ich dann mit mehreren Einzelkinder rumhantieren wollen, wenn es im Endeffekt doch das gleiche ist. Wäre das nicht unnötige Verwirrung?

    Wenn man sich die Aufgabenstellung entsprechend zurechtrückt kann man sich so etwas denken.
    Instanziierbar, nur eine Instanz, Mechanismus um trotzdem eine Instanz erzeugen zu können.
    Wie gesagt ist es ja auch ein Singleton, der sich aber in der Handhabung von dem gewohnten Zugriff per statischer Methode unterscheidet.



  • Ist es mit einer Wrapper-Klasse nicht "etwas" einfacher? Von außen kein "echtes" Singleton und läßt sich behandeln wie getrennte Objekte, wobei es auf das gleiche zugreift...



  • l'abra d'or schrieb:

    FreakY<3Cpp schrieb:

    l'abra d'or schrieb:

    Einzelkind e1;
    Einzelkind e2;
    

    Und beide Einzelkinder sind dann identisch.

    Warum sollte man sowas tuen wollen? Wenn ich ein Singleton habe und nur mit einem Objekt arbeiten muss/brauch, warum sollte ich dann mit mehreren Einzelkinder rumhantieren wollen, wenn es im Endeffekt doch das gleiche ist. Wäre das nicht unnötige Verwirrung?

    Wenn man sich die Aufgabenstellung entsprechend zurechtrückt kann man sich so etwas denken.
    Instanziierbar, nur eine Instanz, Mechanismus um trotzdem eine Instanz erzeugen zu können.
    Wie gesagt ist es ja auch ein Singleton, der sich aber in der Handhabung von dem gewohnten Zugriff per statischer Methode unterscheidet.

    Ist dann kein Singleton mehr. Ist dann eine Klasse mit spezieller Handle-Semantik. Ein Smart-Pointer mit Singleton-Factory kombiniert sozusagen.



  • hustbaer schrieb:

    Ist dann kein Singleton mehr. Ist dann eine Klasse mit spezieller Handle-Semantik. Ein Smart-Pointer mit Singleton-Factory kombiniert sozusagen.

    oder kurz gesagt: monostate



  • Du kannst eine andere Klasse als friend deklarieren. Die kann dann auf den privaten Konstruktor des Singletons zugreifen.

    Um das mit vielen Verschiedenen Klassen zu machen, kannst Du den friend über ein Template bekannt geben:

    template <typename T, class spy = MakeFriends<T> > class Fun
    {
    public:
        Fun& getInstance()
        {
            if ( instance == 0)
            {
                instance = new Fun();
            }
            return instance;
        }
    
        Fun& operator () ( void )
        {
            cout << i << " ";
            cout.flush();
    
            return *this;
        }
    
    private:
        Fun( void ) : i(0)
        {
        }
    
    private:
        T i;
        static Fun* instance; // muss noch extern definiert werden!
    
        friend typename spy; // to make privates accessible for the spy
    };
    
    template <typename U> class MakeFriends
    {
    public:
        MakeFriends(Fun<U>& u) : m(&(u.i)) 
        {
        }
    
        U* m;
    };
    


  • garantiert höchstens einmal instanziiert wird. Verhindern Sie, dass mehrere Instanzen, z.B. mittels [..] trotzdem eine Instanz zu erzeugen.
    

    Wo bitte steht denn, dass mehrere Instanzen erzeugt werden sollen? Wo steht, dass Singleton umgangen werden soll? Erzeugen sie eine Instanz!



  • knivil schrieb:

    garantiert höchstens einmal instanziiert wird. Verhindern Sie, dass mehrere Instanzen, z.B. mittels [..] trotzdem eine Instanz zu erzeugen.
    

    Wo bitte steht denn, dass mehrere Instanzen erzeugt werden sollen? Wo steht, dass Singleton umgangen werden soll? Erzeugen sie eine Instanz!

    so hab ich das auch verstanden.

    allerdings:

    Einzelkind e1;
    Einzelkind e2;
    Einzelkind e3 = e1;
    

    das geht mit nem singleton kaum...
    es würde eben nur über pimpl + ref-counting machbar sein - dann wären die instanzen alle die selben. und dafür gibts nich so wirklich nen (sinnvollen) grund...

    da dort auch nicht groß und breit was von pseudocode steht, würd ichs doch so blöd machen, dass es mit diesem code-stück geht.
    die nächste vorgabe war wiederrum, dass man im dtor eine ausgabe macht - und der nur ein einziges mal aufgerufen werden darf...
    ich habe das so verstanden, dass es der dtor von einzelkind sein soll und nicht der dtor der in einzelkind gekapselten klasse...

    folglich würd ich dem prof auch ne mail schicken und ne url zu dem thread mitschicken...

    bb



  • unskilled schrieb:

    das geht mit nem singleton kaum...
    es würde eben nur über pimpl + ref-counting machbar sein - dann wären die instanzen alle die selben. und dafür gibts nich so wirklich nen (sinnvollen) grund...

    monostate 🙄

    gibt sehr wohl gruende warum man das so haben will... und refcounting ist nicht notwendig...


Anmelden zum Antworten