Deserialisierung - doppelten Initialisierungscode vermeiden
-
tststst ... virtuelle Methoden im Konstruktor Wie waere es mit einer Factory?
Ich will
Genau das ist das Problem. Dein Plan ist schlecht. Die Maengeln kennst du bereits. Warum muss deserialize im Konstruktor aufgerufen werden?
Wie kann ich sicherstellen, dass Deserialize in der am meisten abgeleiteten Klasse in dem entsprechenden Konstruktor aufgerufen wird (und nur da)?
Fang erst garnicht damit an. Ausserdem wuerde das nichts aendern.
-
Der sinn davon deserialize im konstruktor aufzurufen ist ein objekt direkt vom netzwerk aus zu erstellen.
Und ich wollte vermeiden, dass ich mehrere versionen von deserialize habe, deswegen benutze ich die selbe methode zum updaten und im konstruktor.Wie würdest du es denn machen? Von außen erst irgendwie initialisieren und dann deserialize aufrufen? Das ist eigentlich nicht wirklich möglich, weil jedes GameObject beim erstellen eine eindeutige ID zugewiesen bekommt und die id mit übers netzwerk gesendet wird. Wenn dann müsste ich zuerst mit einer ungültigen Id initialisieren und diese dann überschreiben. Wirklich toll finde ich das aber auch nicht.
Wie stellst du dir das mit der factory vor? Soll die factory dann ein objekt erst defaultkonstruieren und dann deserialize aufrufen?
-
Was, wenn deine Netzwerkdaten fehlerhaft sind? Exceptions? Ja, die Factory erstellt ein Objekt. Ja, die Factory erstellt alle Objekte, d.h. sie entscheidet auch ueber die ID. Ja sie ruft irgendwie deserialize auf. Deserialize muss aber keine Methode von GameObject sein.
-
Wenn Deserialize keine methode von gameobject ist, dann muss ich friend oder eine ganze menge von accessor methoden verwenden, ich wüsste nicht, wie ich das sonst implementieren sollte. Ich sehe auch keinen Vorteil darrin, die Deserialize-Methode auszulagern.
Das mit der Factory ist im prinzip machbar, da ist nur das problem mit der id, aber dafür könnte ich eine lösung finden.
Ich benutze eine Netzwerkbibliothek, die dafür sorgt, dass die Daten fehlerfrei übertragen werden. Bisher hatte ich nie Probleme mit fehlerhaften Daten und ich wüsste nicht, warum ich damit jemals probleme kriegen sollte. Falls die Daten wirklich fehlerhaft sein sollten, fliegt höchstwahrscheinlich eine exception.
-
Virtueller Methodenaufruf im Konstruktor ruft per Definition nicht die Methode der "am meisten abgeleiteten Klasse" auf. Selbige ist zu dem Zeitpunkt da du im Konstruktor der Basis bist noch gar nicht konstruiert.
Q schrieb:
Wie stellst du dir das mit der factory vor? Soll die factory dann ein objekt erst defaultkonstruieren und dann deserialize aufrufen?
Die Factory kann einfach einen entsprechenden konkreten Konstruktor aufrufen, der dann eben Deserialize macht. Oder eine konkrete Deserialize Funktion, die eben ein neues Objekt erzeugt, oder sonstwas. Der Punkt ist: Die Factory kennt den konkreten Typ und daher gibts keinen Grund für den virtuellen Methodenaufruf im Konstruktor der Basis, der eben aus Prinzip nicht das von dir erwartete Ergebnis liefern kann.
-
dot schrieb:
virtuelle Methodenaufruf im Konstruktor ruft per Definition nicht die Methode der "am meisten abgeleiteten Klasse" auf. Selbige ist zu dem Zeitpunkt da du im Konstruktor der Basisklasse bist noch gar nicht fertig initialisiert.
Ich rufe das deserialize ja nicht aus der basis auf, das war oben beim codebeispiel vielleicht etwas irreführend. Ich wollte da nur die Struktur zeigen.
Das Deserialize wird im Moment immer nur aus dem konstruktor der am meisten abgeleiteten klasse aufgerufen, was dann auch funktioniert, nur nicht besonders flexibel ist (wenn ich z.B. davon wieder ableite funktioniert es nicht mehr).
Die methode ist eigentlich nur virtuell, damit jede ableitende klasse etwas zum vorgang des deserialisierens hinzufügen kann. Alternativ könnte man die methoden der basisklasse auch verdecken, aber ich denke nicht das das viel besser ist.
-
Der Konstruktor ruft keine in der konkreten Klasse implementierten virtuellen Methoden auf. Alles andere ist Glueck, bzw. nicht definiertes Verhalten.
-
Q schrieb:
Das Deserialize wird im Moment immer nur aus dem konstruktor der am meisten abgeleiteten klasse aufgerufen, was dann auch funktioniert, nur nicht besonders flexibel ist (wenn ich z.B. davon wieder ableite funktioniert es nicht mehr).
Ist es so, daß nur die am meisten abgeleiteten Klassen konkret sind und alle anderen Klassen, also die, von denen geerbt wird, abstrakt sind?
Sollte es so sein?
-
Bisher ist es so, dass alle außer den am meisten abgeleiteten klassen abstrakt sind und ich habe noch nicht geplant das zu ändern, aber ich könnte mir schon vorstellen, dass irgendwann mal ein fall auftritt in dem ich von einer konkreten klasse erben will.
knivil schrieb:
Der Konstruktor ruft keine in der konkreten Klasse implementierten virtuellen Methoden auf. Alles andere ist Glueck, bzw. nicht definiertes Verhalten.
Wenn ich folgendes hab:
class Base { public: virtual void A(){} }; class Derived : public Base { public: Derived(){A();} virtual void A() override {} };
Dann ist das verhalten vom Derived konstruktor doch wohl definiert.
Ich rufe virtuelle methoden nur in den am weitesten abgeleiteten Klassen auf.
-
Welche virtuelle Methode A() soll denn im Konstruktor von Derived aufgerufen werden, die von Base oder die von Derived? Wenn es Derived::A() sein soll, muss ich dich enttaeuschen, du hast reines Glueck.
Ansonsten gibt es ziemlich weit am Ende auch etwas zu virtuellen Funktionen: http://www.slideshare.net/olvemaudal/deep-c
-
Es sollte Derived::A() sein. Wundert mich jetzt sehr, dass das nicht definiert ist.
Aber vielen Dank für eure Hilfe, ich werde das dann mit der Factory einbauen, das hat auch noch einen anderen positiven nebeneffekt.Vorher hatte ich beim erstellen vom netzwerk einen großen switch-case block, ich werde das dann vermutlich durch die Fabrik ersetzen und in der fabrik dann eine map benutzen, die enum-werte auf funktionen mappt, die einen konstruktor mit new aufrufen.
Jede konrete Game-Objekt-Klasse registriert sich dann bei der Factory.Ich habe vor, die Factory dann statisch und global zu machen (oder singleton), damit sich jeder dort registrieren kann. Nur gibt es dann evtl. Probleme mit der initialisierungsreiehenfolge...
Habt ihr dazu noch tipps?