Problem mit Singleton Pattern und dynamisches Löschen des Objekts
-
Hallo Leute!
Ich will etwas fragen. Mein Programm benutzt das Singleton Pattern folgenderweise:class A { static A* pa; A(){/*...*/} // unserer Konstruktor! A(A&){} //leerer Konstruktorrumpf - brauchen wir nicht! A& operator=(const A&) {return *this;} //etwas idiotisches, aber dem Kompilator reicht es :D brauchen wir nicht! static void destroy() { delete pa; } public: ~A() { /*...*/ static void create() { if(!pa) pa = new A(); } static A& self() { return *pa; } void letzteAnweisung() { /*...*/ destroy();//ruft den Destruktor von A, also von *this, dieser Klase, oops, ist das OK? } }; /*...*/ A* A::pa = 0;Man benutzt die Klasse so:
A::create(); A::self().irgendwelche_methode_von_A(); A::self().letzteAnweisung();// danach wird das Objekt gelöscht //A::destroy(); -> nicht erlaubt wegen "private". Es muss immer letzteAnweisung() durchgeführt werden, bevor A gelöscht wird.Ok, das Problem: "letzteAnweisung()" ruft die statische Methode "destroy()", die das Objekt selbst löscht. Ist das OK? Bemerken Sie, dass "letzteAnweisung()" eine NICHT-statische Methode ist.
Danke im Voraus!
-
also.
erstmal deine create-methode find ich nciht gut. ein singleton muss so aussehen, als wäre es immer da. d.h. warum übernimmst du das erstellen nicht in der self-methode?static A& self() { static A a; return a; };oder eben mit pointern.
Das löschen von singletons am programmende ist immer ein bisschen trickreich. Ich hab bis jetzt noch keine lösung gefunden, das automatisch geschehen zu lassen. Warum muss man denn letzteAnweisung aufrufen und darf nich einfach Destroy aufrufen? In Destroy können ja dann auch noch aufräumarbeiten gemacht werden, die in letzteAnweisung gemacht wurden.
zur Frage: ja es ist OK, wenn eine nicht-statische methode eine statische methode aufruft. ANdersrum geht es nicht. Da du aber eh ein singleton hast, kann man quasi alle methdoen als statisch ansehen (nur bildliche gesehen) weil es ja eh nur eine instanz von der klasse gibt.
-
Maxi schrieb:
also.
erstmal deine create-methode find ich nciht gut. ein singleton muss so aussehen, als wäre es immer da. d.h. warum übernimmst du das erstellen nicht in der self-methode?static A& self() { static A a; return a; };oder eben mit pointern.
Weil ich schon eine Menge von Parametern auf A Konstruktor übergeben muss. Kann ich self() überladen, so dass es 2 Versionen gibt:
* mit Parametern - wird A generiert
* ohne Parametern - wird die Instanz von A geliefert.
Im zweiten Fall würde ich A& zurückliefern, weil -> mir zu schwer zu schreiben ist.
destroy() soll nie vom Benutzer frei aufgerufen werden, denn es ist sinnlos. Zusätzlich kann es sein, dass er es vergisst 1 mal aufzurufen.
Meine Lösung - destroy() in eine wichtige Methode einfügen, so dass es sicher ist, das Objekt wird GENAU 1 Mal gelöscht. OK?
-
class A { static A* pa; A(){/*...*/} // unserer Konstruktor! A(const A&); // Konst muss da rein. Es reicht auch eine Deklaration. A& operator=(const A&); // Hier genauso static void destroy() { delete pa; } ~A() {} // Destruktor ebenfalls privat public:´ static A& self() { if(!pa){ pa = new A(); // Eine mehr oder weniger gute möglichkeit: atexit(destroy); } return *pa; // Wie schon andere angemerkt haben, ist das besser. // Die statische Variante ist aber nicht thread-safe. // Und hat paar andere "Effekte" die nicht unbedigt gut sein müssen } };
-