problem mit einem einfachen Singleton
-
Hi leutz!
Ich hab da mal versucht eine singleton klasse zu schreiben, die 1:1 genau so aussieht:#include <iostream> using namespace std; class myClass{ public: int memberInt; static myClass* pSingleton; myClass(){ cout<< "konstruktor wurde aufgerufen"<<endl; memberInt=12345; } inline static myClass* Get(){ if(pSingleton==NULL){ pSingleton=&(myClass()); } return pSingleton; } }; myClass* myClass::pSingleton=NULL; int main(){ myClass myObject=myClass(); cout<<myObject.memberInt<< endl<<endl; //12345=0k cout<<myObject.Get()->memberInt<<endl; //schrott typ 1 cout<<myObject.pSingleton->memberInt<<endl; //schrott typ 2 cout<<endl; cout<<myClass::Get()->memberInt<<endl; //schrott typ 1 cout<<myClass.pSingleton->memberInt<<endl; //schrott typ 2 cout<<myClass::pSingleton->memberInt<<endl; //schrott typ 2 return 0; }also, irgendwie kann ich mir im moment nichts einfacheres vorstellen. Und irgendwie erkenne ich nicht, wo hier überhaupt platz für fehler sein kann. Compiler meckert auch nicht.
Aber das programm funktioniert einfach nicht. Wenn ich versuche auf den singleton pointer zuzugreifen, und dann die membervariable (memberInt) ausgeben zu lassen, kommt da irgendein schrott raus. Dabei spielt es auch noch eine rolle, ob ich direkt auf pSingleton zugreife, oder es mir über die Get() funktion ausgeben lasse. Wie DAS sein kann, verstehe ich überhaupt nicht, es ist doch ein und dieselbe variable, die zwischendurch nirgendwo verändert wird.
Ausserdem verstehe ich nicht wirklich, wozu die ganzen verschiedenen zugriffsoperatoren gut sein sollen, wie unterscheidet sich myClass::pSingleton von myClass.pSingleton??
Wäre wirklich dankbar wenn mir das jemand erklären würde!
Vielen dank im voraus,
MFG andrey
-
Du speicherst die Adresse von einem temporären Objekt. Eine einfaches singleton (meyers-singleton genannt) sähe so aus:
class Singleton { public: Singleton& getSingleton() { static Singleton instance; return instance; } };
-
Mein Compiler meldet nen Fehler bei myClass.Get() denn statische Funktionen ruft man mit myClass::Get() auf.
klassen erstellst du mit new und nicht in dem du den Konstruktor aufrufst. Außerdem sollte ein Singleton ja auch nicht von außen erstellt werden, sondern der Zugriff solte ausschließlich per Get() möglich sein, also solltest du den Konstruktor sowie den Zeiger privat machen:
#include <iostream> using namespace std; class myClass { public: int memberInt; inline static myClass* Get() { if(pSingleton==NULL) { pSingleton= new myClass; } return pSingleton; } private: static myClass* pSingleton; myClass() { cout<< "konstruktor wurde aufgerufen"<<endl; memberInt=12345; } }; myClass* myClass::pSingleton=NULL; int main() { myClass::Get()->memberInt = 123; std::cout << myClass::Get()->memberInt << std::endl; return 0; }mfg.
-
Da hast du jetzt aber ein memory-leak.
Habe in meinem Beispiel oben ne kleinigkeit vergessen, die Methode getSingleton muss natürlich static sein.
Und nicht vergessen den Konstruktor und op= private zu deklarieren.
-
erstma zu der sache mit "private" : jaja, ist schon klar, wollte ich auch später machen, dieses objekt, das in der main erzeugt wird, ist nicht notwendig, war halt nur als kleiner zwischentest da.
das mit dem zugriff "myClass.Get()": seltsam! da hätt ich auch ne fehlermeldung erwartet, aber nein, compiler schweigt...

dann noch ne frage:
klassen erstellst du mit new
"klassen"? w-wwie "Klassen"? wartet mal leutz, hab ich das prinzip etwa völlig falsch verstanden? Hast du da "klasseninstanz" gemeint, oder bin ich da grad auf etwas gestoßen, was ich nur zu verstehen _glaubte_ ?
Was ich da vorhatte: eine klasse zu deklarieren, die als statische variable einen pointer auf eine instanz dieser klasse hat. Wo die instanz liegt (ob aufm heap oder sonstwo) sollte eigentlich egal sein.
Und irgendwie verstehe ich nicht: warum muss diese instanz unbedingt auf dem heap erzeugt werden? Warum funktioniert es nicht, wenn ich diese instanz im normalen speicher erzeuge, und ihre adresse in den pointer speichere?zum memoryleak: nun ja, was man auf dem heap erzeugt, kann man auch wieder entfernen, solang man weis wo es ist, das ist kein problem...
Also, okay, danke schonmal, ich glaube jetzt, dass das problem gelöst ist, wenn ich die instanz auf dem heap erzeuge, aber ich wüsste trotzdem noch gerne, warum das denn jetzt so ist

thx thx thx!

-
Andrey schrieb:
"klassen"? w-wwie "Klassen"? wartet mal leutz, hab ich das prinzip etwa völlig falsch verstanden? Hast du da "klasseninstanz" gemeint, oder bin ich da grad auf etwas gestoßen, was ich nur zu verstehen _glaubte_ ?
Nene, stimmt schon

Objekte oder Instanzen erzeugst Du mit new auf dem Heap oder eben auf dem Stack.Was ich da vorhatte: eine klasse zu deklarieren, die als statische variable einen pointer auf eine instanz dieser klasse hat. Wo die instanz liegt (ob aufm heap oder sonstwo) sollte eigentlich egal sein.
Und da liegt der Hase im Pfeffer: Wo die Instanz liegt, ist natürlich egal. Aber wie lange sie lebt, eben nicht. Ein mit myclass() erzeugtes Objekt (wie in Deinem Versuch) ist temporär und lebt nur über die Dauer des Ausdrucks in dem es verwendet wird. Ein mit myclass objekt() erzeugtes Objekt lebt nur bis zur dazugehörigen schliessenden geschweiften Klammer (genauer: bis zum Ende des Scopes). Ein auf dem Heap erzeugtes Objekt lebt bis Du es wieder löscht.
Und irgendwie verstehe ich nicht: warum muss diese instanz unbedingt auf dem heap erzeugt werden? Warum funktioniert es nicht, wenn ich diese instanz im normalen speicher erzeuge, und ihre adresse in den pointer speichere?
1. Muss sie nicht. Eine statische Variable wie lolz gezeigt hat geht auch. Diese lebt dann vermutlich irgendwo im Datenbereich des Programms.
2. Siehe oben, das Objekt lebt eine Zeile tiefer schon nicht mehr. Deine Adresse zeigt auf ein Objekt das es nicht mehr gibt.zum memoryleak: nun ja, was man auf dem heap erzeugt, kann man auch wieder entfernen, solang man weis wo es ist, das ist kein problem...
Ja, nur dass Du auch dran denken musst

Die static-Variante räumt der Compiler automatisch zum Programmende ab.