Singleton als Basisklasse



  • @MaSTaH
    zeig mal mehr code



  • // Implementierung des Singleton-Patterns
        template <class T> class CSingletonPattern
        {
        private:
            static T* m_pInstance; 
            const CSingletonPattern<T>& operator = (const CSingletonPattern<T>&);
            CSingletonPattern(const CSingletonPattern<T>&);
            ~CSingletonPattern() {}
    
        protected:
            CSingletonPattern(){}
    
        public:
            static T* getInstance() {
                return m_pInstance;
            }
        };
        template<class T> T* CSingletonPattern<T>::m_pInstance = new T;
        template<class T> std::auto_ptr<T>g_apInstance(CSingletonPattern<T>::m_pInstance);
    

    Irgendwas ist da falsch in der auto_ptr-Zeile, komme aber nicht dahinter 😕



  • Mist, doch kein Denkfehler...
    Ich mag langsam meine eigene Idee nicht mehr...

    @MaSTaH: ich hab eher an so was gedacht, um keine unfertigen Objekte zu kriegen:

    template <class T> 
    class AutoHandle {
        auto_ptr<T> object;
    
    public:
        AutoHandle () : object(new T) {}
    
        operator T * () const { return object.get(); }
    };
    
    template <class T>
    class SingletonPattern {
        static AutoHandle<T> Single; 
    
        const SingletonPattern<T> &operator = (const SingletonPattern<T> &);
        SingletonPattern (const SingletonPattern<T> &);
    
    protected:
        SingletonPattern () {}
        virtual ~SingletonPattern () {}
    
    public:
        static T *getInstance () { return Single; }
    };
    
    template <class T>
    AutoHandle<T> SingletonPattern<T>::Single;
    
    class Singleton : public SingletonPattern<Singleton> {
        friend class AutoHandle<Singleton>;
    
        int x;
        Singleton () {}
    
    public:
    
        int getX () const { return x; }
        void setX (int x_) { x = x_; }
    };
    

    wäh pfui, vergebt mir, falls ich da fehler gemacht hab, ich mag den Code langsam echt nicht mehr...



  • dann muss du schon so

    // Implementierung des Singleton-Patterns
        template <class T> class CSingletonPattern
        {
        private:
            static std::auto_ptr<T> m_pInstance; 
            const CSingletonPattern<T>& operator = (const CSingletonPattern<T>&);
            CSingletonPattern(const CSingletonPattern<T>&);
            ~CSingletonPattern() {}
    
        protected:
            CSingletonPattern(){}
    
        public:
            static T* getInstance() {
                return &*m_pInstance;
            }
        };
        template<class T> std::auto_ptr<T> CSingletonPattern<T>::m_pInstance( new T );
    

    aber ich finde ein Meyers-Singleton besser http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=Singleton#Answ

    template <class T> 
        class CSingletonPattern
        {
        private:
            const CSingletonPattern<T>& operator = (const CSingletonPattern<T>&);
            CSingletonPattern(const CSingletonPattern<T>&);
            ~CSingletonPattern() {}
    
        protected:
            CSingletonPattern(){}
    
        public:
            static T& getInstance() 
            {
                static T instanz;
                return instanz;
            }
        };
    


  • Das Meyers-Singleton ist ja schön pragmatisch einfach, aber hat halt eine mächtige Macke, die seinen praktischen Einsatz in größeren Projekten erheblich einschränkt: nicht thread-sicher.

    Man kann das zwar umgehen, indem man die Singletons erstmalig alle mit Dummy-Aufrufen ::instance() holt um sie zu erzeugen, bevor man seine Threads anlegt. Das wiederläuft aber etwas den Gedanken, daß ein Singleton ja nur konstruiert werden soll, wenn es auch mind. einmal verwendet wird.

    Weiterhin ist die Abbau-Reihenfolge kritisch, läßt sich kaum kontrollieren.

    Siehe dazu:
    http://www.c-plusplus.net/titelanzeige.php?ISBN=0201432935

    (Sorry, Layout ist noch nicht fertig!)



  • Gibt es auch eine "perfekte" Implementation die keine Macken hat?



  • In dem genannten Buch (zu schade, daß es die dt. Version nicht mehr gibt... 😞 ) ist eine Implementation enthalten... Will man die Sachen wie Templateschablone, Threadsicherheit und definierte Abbaureihenfolgen alle erfüllt haben, wird aus diesem eigentlich primitivsten aller Design-Pattern eine richtige Monsterimplementation... z.B. Destruktion mit Hilfe von atexit und ähnlichem.

    Es gibt noch eine Implementation in der Bibliothek "ACE", Suchbegriffe dazu sind "Double-Checked-Locking-Pattern", "Vlissides", "Pattern Hatching April 1996".



  • Marc++us der fragt beim Aufruf der Seite nach einem User/PW für php/dba Access.



  • in den buch modern c++ desing gibt ein template was das können sollte, die lib (loki) zum buch gibt kostenlos online zum downloaden



  • Ich bin der Meinung, dass man sich vorher überlegen sollte, ob man vielleicht nicht doch etwas anderes als ein Singleton will: eine Instanz der Klasse, die überall diesselbe sein soll (sowas wie global)
    Dann reichte nämlich das:

    template <class T>
    class SingletonPattern : public T {
        static SingletonPattern<T> *single;
        SingletonPattern () {}
        SingletonPattern (const SingletonPattern &);
        const SingletonPattern &operator = (const SingletonPattern &);
    
    public:
        static T &getInstance () { return *single; }
    };
    template <class T> SingletonPattern<T> *SingletonPattern<T>::single = new SingletonPattern<T>;
    
    class Klasse {
        int x;
    
    public:
        int getX () const { return x; }
        void setX (int x_) { x = x_; }
    };
    
    int main () {
        {
            Klasse &s = SingletonPattern<Klasse>::getInstance();
            cout << s.getX () << endl;
            s.setX (10);
        }
    
        {
            Klasse &s = SingletonPattern<Klasse>::getInstance();
            cout << s.getX () << endl;
        }
        return 0;
    }
    

    Der Begriff SingletonPattern ist vielleicht irreführend, aber ich wollte die Namen nicht neu schreiben. Ein Singleton ist für mich ein Verbot für den Benutzer, mehrere Instanzen zu erstellen (...)
    Aber meistens/oft braucht man eben so etwas, wie oben beschrieben



  • Ja, das Problem daran sind nur die MemoryLeaks



  • Verdammt nochmal, ich brauche sowas auch gerade.
    Kennt nicht jemand ein gutes Online-Tutorial für so ein perfektes SingleTon, gut erklärt?



  • Ah, hab auch was Feines gefunden: http://www.informatik.fh-muenchen.de/schieder/seminar-oo-modellieren-ws97-98/f7alpha1.informatik.fh-muenchen.de/ifw94005/singleton.html#Absicht
    Ist zwar ein bißchen mieses C++, aber grundsätzlich wird da viel für ein gutes Singleton zusammengebracht. 🙂

    MfG MAV



  • Will man die Sachen wie Templateschablone, Threadsicherheit und definierte Abbaureihenfolgen alle erfüllt haben, wird aus diesem eigentlich primitivsten aller Design-Pattern eine richtige Monsterimplementation

    Und statt diese Monsterimplementation selbst zu basteln, greift man einfach zu Lokis (Andrei Alexandrescus Bibliothek zu "Modern C++ Design") SingletonHolder. Da kann man sich mit Policies alles fein zusammensetzen.



  • Ich bin ehrlichgesagt kein Fan von fremden Libs.
    Ich muss nicht unbedingt Templates verwenden, aber kann man es nicht irgendwie mit einem void* Pointer und nem' Static Cast machen?

    MfG MAV



  • Wozu überhaupt so eine Basisklasse?
    Ich meine das sind doch letztendlich nur drei Zeilen die aus einer Klasse so ein Singleton machen..

    Das Thread-Problem hab ich neulich gehabt (das war ein Spaß, bis ich irgendwann gemerkt hab wo die Problematik liegt ;)).



  • Original erstellt von Mis2com:
    Ich bin ehrlichgesagt kein Fan von fremden Libs.

    Warum das? 😕 Sowas erspart einem oft viel Arbeit!



  • Tja, weil ich mir das Zeugs am besten selber zusammencode.

    Kann mir nicht bitte jemand eine einfache SingleTon-basisklasse geben, die mit ganz gewöhnlichen Zeigern arbeitet.
    Wenn ich für alle die Klassen SingleTons brauche, dann ist es dach auch viel mehr OOP das so abzuleiten.
    Ich habe das Gefühl, dass meine Engine total schlecht aufgebaut ist, wenn sie die SingleTonklasse nicht extra ableitet. 😞

    MfG MAV

    [ Dieser Beitrag wurde am 15.04.2003 um 22:22 Uhr von Mis2com editiert. ]



  • Original erstellt von nman:
    Warum das? 😕 Sowas erspart einem oft viel Arbeit![/QB]

    Und schaft Abhängigkeiten. Bevor ich mir da irgendeine dicke Lib für solche ("unwichtigen") Aufgaben in's Projekt reinknalle, schreib ich lieber einmal am Anfang das Proramms ein get() rein.

    Als ich neulich auf das Thread-Problem gestoßen bin, wurde ich ohnehin skeptisch was so ein Singleton betrifft. Finde es irgendwie schöner, wenn man Kontrolle darüber hat, wann etwas initialisiert wird. Zumindest solange es sich nicht um ganz triviale Dinge handelt.



  • Hallo.

    Habe mal den Code zusammengebraut:

    class SingleTon
    {
    public:
        static SingleTon& Instance()
        {
            if(instance == 0)
                instance = new SingleTon;
    
            return *instance;
        }
        ~SingleTon()
        {
            delete instance;
        }
    protected:
        SingleTon() {}
    private:
        static SingleTon* instance;
    };
    
    SingleTon* SingleTon::instance;
    
    class Test : public SingleTon
    {
    public:
        void setA(int a) {m_a = a;}
        int  getA()      {return m_a;}
    private:
        int m_a;
    };
    
    ofstream ofs;
    
    void func1()
    {
        Test& t = (Test&)Test::Instance();
        ofs << t.getA();
        t.setA(120);
    }
    
    void func2()
    {
        Test& t = (Test&)Test::Instance();
        ofs << t.getA();
        t.setA(130);
    }
    
    int main()
    {
        ofs.open("D:\\daten.txt");
    
        ofs << "Start...\n";
    
        Test& t = (Test&)Test::Instance();
        t.setA(100);
    
        ofs << t.getA() << '\n';
    
        func1();
    
        ofs << t.getA();
    
        func2();
    
        ofs << t.getA();
    
        ofs << "Ende...\n";
    
        ofs.close();    
    
        return 0;
    }
    

    Funktioniert bestens!
    Ich habe ein Testprogramm drangekuppelt, dass auch überprüft ob das nicht immer die gleichen Instanzen sind...
    Nun, also was ist dagegen einzuwenden? 🙂

    MfG MAV

    [ Dieser Beitrag wurde am 15.04.2003 um 22:28 Uhr von Mis2com editiert. ]


Anmelden zum Antworten