2016-09-22 4 views
-2

Die Verwendung ist, um .inance Zugriff, auch doppelte Objekte dieser Klassen zu verhindern.Verhindern Sie doppelte Objekte in Klassen/Instanzenzugriff mit Singleton

Ist dies eine gute Code-Implementierung eines Singleton?

template <typename T> class singleton 
{ 
public: 
    static T *ms_singleton; 

    singleton() 
    { 
     assert(!ms_singleton); 
     long offset = (long)(T *) 1 - (long)(singleton <T> *)(T *) 1; 
     ms_singleton = (T *)((long) this + offset); 
    } 

    virtual ~singleton() 
    { 
     assert(ms_singleton); 
     ms_singleton = 0; 
    } 

    static T &instance() 
    { 
     assert(ms_singleton); 
     return (*ms_singleton); 
    } 

    static T &Instance() 
    { 
     assert(ms_singleton); 
     return (*ms_singleton); 
    } 

    static T *instance_ptr() 
    { 
     return (ms_singleton); 
    } 
}; 
template <typename T> T *singleton <T>::ms_singleton = NULL; 

Wie ich es verwenden:

class test1: public singleton<test2> 
{ 
    // Something 
}; 

Wenn nicht, was hier falsch ist? Was soll ich hier umschreiben?

+2

Warum nicht Meyers, wenn Sie wirklich wollen Singleton. – Jarod42

+1

Dies ist kein Singleton, da Sie einen öffentlichen Konstruktor haben. – NathanOliver

+0

Und Ihre Offset-Berechnung mit Besetzung ist seltsam ... was möchten Sie erreichen? – Jarod42

Antwort

1

Ihre Singleton-Klasse hat einige seltsame Dinge. Wie Sie sich auf den Konstruktor verlassen, um eine Debug-Build-Laufzeitprüfung zu machen, ob er in Ihrem Konstruktor konstruiert werden kann oder nicht.

Eine typische Singleton-Klasse hat die Konstruktoren privat, so dass sie nur durch die Accessor-Funktion erstellt werden kann. Es sollte sich auch nicht auf z.B. assert ist ein Makro, das in Release-Builds deaktiviert ist.

Eine einfache nicht-vererbbaren Singletonklasse könnte wie folgt aussehen:

class Singleton 
{ 
public: 
    static Singleton& instance() 
    { 
     static Singleton actual_instance; 
     return actual_instance; 
    } 

    // Other public member functions 

private: 
    // Private constructor 
    Singleton() = default; 
}; 

Durch den Konstruktor privat ist, es bedeutet, dass niemand sonst keine Instanz zu konstruieren versuchen kann. Dies bedeutet auch, dass dies zum Zeitpunkt der Kompilierung vom Compiler selbst überprüft wird.

Auch wenn die tatsächliche Instanz des Objekts als statische Variable und bei der Definition in der Accessor-Funktion initialisiert wird, bedeutet dies, dass die Erstellung der Instanz Thread-sicher ist.


es zu erweitern und es generische machen wie Sie scheinen wollen, dann müssen Sie den Basisklassenkonstruktor geschützt machen. Sie müssen auch die Basisklasse in der geerbten Klasse friend machen.

Die untergeordnete Klasse muss den Konstruktor weiterhin privat machen, um eine versehentliche Konstruktion zu verhindern.

die Basisklasse aktualisiert dann so etwas wie

template<typename T> 
class Singleton 
{ 
public: 
    static T& instance() 
    { 
     static T actual_instance; 
     return actual_instance; 
    } 

protected: 
    Singleton() = default; 
}; 

Ein Kind-Klasse verwenden aussehen würde Singleton könnte etwa so aussehen

class ChildSingleton : public Singleton<ChildSingleton> 
{ 
public: 
    // Public member functions... 

private: 
    friend class Singleton<ChildSingleton>; 

    // Private constructor 
    ChildSingleton() = default; 
}; 
+0

Gibt es einen Grund, 'statische Singleton * zu verwenden? actual_instance = new Singleton; 'over' statischer Singleton actual_instance; '? – NathanOliver

+0

@NathanOliver Nicht wirklich nein, wahrscheinlich ein Problem mit meinem Denken. –

+0

Schau, was clang 3.4 sagt http://prntscr.com/cl331l – Smartx221

Verwandte Themen