Singletons in C++
-
volkard schrieb:
multiluigi schrieb:
der unterschied ist, dass createInstance() nur einmal aufgerufen werden darf und getInstance() keine instanz mehr erzeugt.
das würde der benutzer doch eh falsch machen. deswegen schützt man selbstverständlich createInstance() derart, daß es unschädlich ist, wenn ein anderer benutzer es an anderer stelle nochmal aufruft.
quatsch, wieso? die funktion ist dazu gedacht, einmal an einer passenden stelle aufgerufen zu werden. und der name zeigt auch eindeutig, dass hier etwas erzeugt wird. erneutes aufrufen wäre ein grober fehler, der nicht einfach still ignoriert werden darf.
das soll doch der wesentliche unterschied zum üblichen singleton sein, wo der absolute zeitpunkt der erzeugung egal ist.außerdem nennt man es gleich noch um zu GetInstance().
das erzeugen der instanz und das holen der instanz wären hier aber zwei unterschiedliche dinge, mit absicht.
es gibt dann also eine feste stelle im programm, wo der singleton initialisiert wird, statt es on demand zu machen.
ruf doch einfach an der einen festgelegten stelle GetInstance() auf. da hat doch keiner was dagegen.
siehe oben. erzeugen und holen sind unterschiedliche dinge.
ist das immer noch ein singleton oder gibt es dafür eine speziellere bezeichnung?
klar ist das auch ein singleton. aber der hat keinen speziellen namen, weil er in der praxis nicht gesichtet wird.
ist das so? woher weißt du das?
-
multiluigi schrieb:
ist das so? woher weißt du das?
Anmeldungsdatum: 06.04.2000
er wäre in den vergangenen 9 jahren hier aufgetaucht. die meiste zeit habe ich davon mitgekriegt und keinen solchen singleton gesehen.
außerdem würde ich erwarten, daß alexandrescu in "modern c++ design" seinen 24 erzeugbaren singletons dann noch ein paar hinzugefügt hatte. hat er aber nicht.warum sollte es denn ein fehler sein, createInstance() ein weiteres mal aufzurufen? das nur-einmal-aufrufen kannste doch nur garantieren, wenn der aufruf am anfang der main() steht und du vorher keinen code ausführst. das ist unfug. ein beispiel für einen singleton sei der standarddrucker. irgendwann kommst du auf die idee, einen kostruktor zu schreiben, in dem der drucker verwendet wird und irgendwann machst von diesem typ eine globale variable, und schwupps, wird der drucker benutzt *bevor* die main() gestartet wird, vor crateInstance() und der rechner schmiert ab. das nur-einmal-starten löst GetInstance() gut. und das in-der-richtigen-reihenfolge-starten auch, denn jeder der den drucker braucht, sichert einfach ab, daß der drucker bereits zur verfügung steht, bevor er benutzt wird. wo ist nur das problem?
-
warum sollte es denn ein fehler sein, createInstance() ein weiteres mal aufzurufen?
weil es oft ein fehler ist, bereits initialisierte programmteile nochmal zu initialisieren. ich möchte schon gerne wissen, wenn das passiert.
das nur-einmal-aufrufen kannste doch nur garantieren, wenn der aufruf am anfang der main() steht und du vorher keinen code ausführst. das ist unfug. ein beispiel für einen singleton sei der standarddrucker.
ein beispiel für einen singleton sei eine logging-klasse. die logdatei wird bei der erzeugung des loggers angelegt, eine eventuell bereits vorhandene damit gelöscht.
wenn nun ein destruktor eines globalen objekts etwas ins log schreiben will, ruft er getInstance() vom singleton auf. dummerweise war der singleton schon zerstört, wird jetzt neu angelegt, und die logdatei ist futsch.
mein singleton macht den programmierer statt dessen darauf aufmerksam, dass hier irgendwas nicht passt.es geht mir nicht darum, dass ich alle denkbare fälle mit meinem spezialsingleton erschlagen muss. ich halte es nur in manchen fällen für sehr praktisch, wenn man die zeitpunkte von konstruktion und destruktion selbst festlegen kann, weil der singleton einfach nur während main() existieren soll und außerhalb nicht. wenn es anders sein soll, nehme ich einen andere strategie.
-
@multiluigi
Also wenn du dich für Sonderfälle und ihre Lösung interessierst, dann empfehle ich dir das schon genannte "Modern C++ Design" von Alexandrescu. Er hat da die gängigen Problem (auch die, die du genannt hast) erklärt. (Natürlich mit der Implementierung).
-
multiluigi schrieb:
weil es oft ein fehler ist, bereits initialisierte programmteile nochmal zu initialisieren. ich möchte schon gerne wissen, wenn das passiert.
Die Idee eines Singletons ist aber eine andere.
Klar koennte man soetwas dummes machen wie explizit instanziieren - aber das schafft meistens nur mehr Probleme und bringt keinen Nutzen.Denn der ganze Trick eines Singletons ist ja, dass er einfach da ist. Das wirkliche Problem dass es zu loesen gilt ist die Destruktion. Meyers Singleton ist da eine gute Antwort. Manchmal reicht das nicht, dann braucht man einen Phoenix. Aber damit hat man bereits 99% aller Faelle abgehakt.
ein beispiel für einen singleton sei eine logging-klasse. die logdatei wird bei der erzeugung des loggers angelegt, eine eventuell bereits vorhandene damit gelöscht.
wenn nun ein destruktor eines globalen objekts etwas ins log schreiben will, ruft er getInstance() vom singleton auf. dummerweise war der singleton schon zerstört, wird jetzt neu angelegt, und die logdatei ist futsch.
mein singleton macht den programmierer statt dessen darauf aufmerksam, dass hier irgendwas nicht passt.Designfehler des Loggingstreams.
Du zerstoerst nie eine Log Datei, du rollst sie nur over.Aber, das ganze ist sowieso eine Themenverfehlung, da der Singleton weiss wenn er wiederaufersteht - es ist trivial da eine spezielle Abfrage einzubauen.
Der Meyers Singleton kann ja zB nicht wiederauferstehen...
es geht mir nicht darum, dass ich alle denkbare fälle mit meinem spezialsingleton erschlagen muss. ich halte es nur in manchen fällen für sehr praktisch, wenn man die zeitpunkte von konstruktion und destruktion selbst festlegen kann, weil der singleton einfach nur während main() existieren soll und außerhalb nicht. wenn es anders sein soll, nehme ich einen andere strategie.
nur waehrend main()? Also waehrend der Laufzeit des Programmes?
Wo ist da ein Spezialfall?Wenn du aber den Singleton immer selber erstellen und zerstoeren willst, willkommen in der Welt von RAII. Dann braucht man den ganzen Aufwand von Singletons ja garnicht.
Ein Singleton bietet naemlich noch ein entscheidendes Feature: er wird nur dann erstellt wenn er gebraucht wird.
Und wenn man richtig programmiert, dann packt man den Singleton sowieso in eine Klasse und dann kann man, wenn man spaeter merkt dass ein Meyers Singleton nicht reicht, immer noch eine komplexere Implementierung waehlen. Aber generell immer alles mit Komplexitaet zu erschlagen ist keine gute Idee. Viel besser ist es zu abstrahieren - und dann, wenn noetig - die komplexitaet einbauen.
-
Shade Of Mine schrieb:
Du zerstoerst nie eine Log Datei, du rollst sie nur over.
Was soll den eine Logdatei "over rollen" sein?
-
Frage 10443 schrieb:
Shade Of Mine schrieb:
Du zerstoerst nie eine Log Datei, du rollst sie nur over.
Was soll den eine Logdatei "over rollen" sein?
Keine Ahnung wie man auf deutsch dazu sagt.
Du nimmst die aktuelle Log Datei und verschiebst sie, meistens mit einem Timestamp dann im Namen und erstellst eine neue LogDatei.
zB um Mitternacht nimmst du alle Logdateien und benennst sie von foo.log in foo-2008-01-02.log um und erstellst eine leere foo.log.
So verlierst du keine Logdateien und die Dateien werden dennoch nicht zu gross. Du kannst so auch recht simpel die laenge fuer die eine logdatei aufgehoben werden soll eingrenzen - oder backupen oder sonstwas machen.
-
Shade Of Mine schrieb:
Keine Ahnung wie man auf deutsch dazu sagt.
da sagt man auf deutsch rotaten dazu.
-
Was ist für den Fall, dass man das Singleton bei der Konstruktion zur Laufzeit parametrisieren will? Für den Fall wäre eine separate createInstance-Methode doch zweckmäßig? Ansonsten bliebe vielleicht nocht der Umweg über globale Variablen, was aber auch nicht mehr Sinn macht, denn wenn die nicht gesetzt werden, bevor das Singleton von einem Clienten gebraucht wird, führt es auch zu einem Fehler.
Ein Fall wäre das z.B. wenn ein Singleton einen Zeiger auf ein nicht-singleton Objekt halten will / muss.
-
ah, du willst deine globale variable als singleton verkaufen. ja, da ist wohl createInstance() der weg in C.
-
Ich will gar nichts, das war nur ein Gedanke. Und nach der originalen Definition im GoF-Buch ist die Absicht eines Singletons folgende:
Ensure a class only has one instance, and provide a global point of access to it.
...und das ist ja immer noch gewährleistet. Eure Definiton erweitert das wohl noch darum, dass ein Singleton jederzeit verfügbar ist. Ich halte createInstance() also schon noch für ok, auch wenn es mir auch nicht grad gut gefällt.
-
nur waehrend main()? Also waehrend der Laufzeit des Programmes?
Wo ist da ein Spezialfall?ein globales objekt wird vor main() erzeugt und nach main() zerstört.
Wenn du aber den Singleton immer selber erstellen und zerstoeren willst, willkommen in der Welt von RAII. Dann braucht man den ganzen Aufwand von Singletons ja garnicht.
was meinst du mit "immer"? singletons dieser art werden in der regel einmal erzeugt (zum programmstart) und einmal zerstört (zum programmende). geht auch anders, wenn man es will, aber dafür nimmt man lieber einen anderen singleton, der dafür gebaut ist.
Ein Singleton bietet naemlich noch ein entscheidendes Feature: er wird nur dann erstellt wenn er gebraucht wird.
wenn das im einzelfall wichtig ist, dann nimmt man auch einen singleton, der das leistet. meiner tut das nicht und das ist auch so gewollt.
schade, dass hier nicht viel mehr als "dumm", "ich weiß es besser" und am-thema-vorbei-gerede kommt. nicht sehr überzeugend.