Mechanismus zum Umgehen eines Singletons !



  • 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...



  • monostate

    ok - der codeschnipsel würde dennoch nicht die angegebenen forderungen erfüllen.
    ich bleibe bei meiner aussage, dass die angaben mit c++ nicht zu implementieren sind, da das hier ja schon gegeben ist:

    struct Einzelkind
    {
     /*...*/
    
      static unsigned int dtor_count = 0;
    
      ~Einzelkind()
      {
        ++dtor_count;
      }
    };
    
    /*...*/
    
    int main()
    {
      Einzelkind e1;
      Einzelkind e2;
      Einzelkind e3 = e1;
    
      assert(Einzelkind::dtor_count == 1);
    }
    

    bb



  • Shade Of Mine schrieb:

    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

    monostate verstehe ich anders.

    Hier:
    Objekt wird mit Erzeugen des 1. Handle initialisiert und mit Zerstören des letzten Handles de-initialisiert.

    Monostate:
    Evtl. auch "lazy" Initialisierung mit Erzeugen des 1. Handle, aber keine sinnvolle De-Initialisierung möglich, da man damit rechnet dass Client Code andauernd extrem kurzlebige Objekte erzeugt (und eben gleich wieder zerstört).

    Ist IMO ein u.U. sehr wichtiger Unterschied.



  • hustbaer schrieb:

    Hier:
    Objekt wird mit Erzeugen des 1. Handle initialisiert und mit Zerstören des letzten Handles de-initialisiert.

    Davon steht hier nichts.
    Aber auch das ist mit monostate problemlos moeglich.

    Monostate:
    Evtl. auch "lazy" Initialisierung mit Erzeugen des 1. Handle, aber keine sinnvolle De-Initialisierung möglich, da man damit rechnet dass Client Code andauernd extrem kurzlebige Objekte erzeugt (und eben gleich wieder zerstört).

    das ist deine enge definition eines monostates. Aber monostate ist ein Design Pattern, dh es beschreibt nur abstakt eine Loesung fuer ein Problem. Wie du es genau implementierst haengt von der Situation ab.



  • Shade Of Mine schrieb:

    Monostate:
    Evtl. auch "lazy" Initialisierung mit Erzeugen des 1. Handle, aber keine sinnvolle De-Initialisierung möglich, da man damit rechnet dass Client Code andauernd extrem kurzlebige Objekte erzeugt (und eben gleich wieder zerstört).

    das ist deine enge definition eines monostates. Aber monostate ist ein Design Pattern, dh es beschreibt nur abstakt eine Loesung fuer ein Problem. Wie du es genau implementierst haengt von der Situation ab.

    Dann hatte ich da was falsch verstanden.


Anmelden zum Antworten