 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Andreas Pokorny Guest
|
Posted: Sun Dec 28, 2003 7:11 pm Post subject: Serialisierungskonzept |
|
|
Ich beschäftige mich dieser Tage mit möglichst formatunabhängiger
(De)Serialisierug ( oder Persistenz ) von Objekten. Ziel war ein System
das vom Benutzer verwendet wird um formatfrei Elemente in Klassen zu
deklarieren die dann von dem jeweiligen Serialisierer verwendet werden
um die Daten auszulesen oder in neu erstellte Objekte zu schreiben.
Nachdem das System nun weitesgehnd funktionsfähig zu sein scheint und
der XML-Serialisierer funktioniert, kommen mir Zweifel ob es die Mühe
wert und ob das Konzept nicht gleichzeitig zu einschränkend und zu
komplex ist.
Das System hat folgenden Aufbau:
Jeder Typ der serialisiert werden soll definiert eine zugängliche
Struktur Typ::serialization diese sollte von serializeable<Typ,
ListeMitMetaTypen> abgeleitet sein. Dann müssen noch zwei Funktionen
implementiert werden doch dazu später mehr.
ListeMitMetaTypen sollte ein mpl::vector oder eine mpl::list sein.
Deren Elemente spiegeln die Elemente des zu serialisierenden Typs
wieder. Derzeit stehen dazu die Schablonen s_element, s_data, s_class
und s_container zur Verfügung.
s_element<Element>: charackterisiert eine einzelne Variable vom Typ
Element. Der Typ muss direkt aus dem Strom parsebar sein. ( im Falle von
XML wird dies als Attribut interpretiert )
s_data<Element>: wie s_element - wird aber bei xml in den
<tag>Innenbereich</tag> geschrieben
s_class<Element>: beschreibt eine Variable eines komplexeren Typen der
selbst wieder eine innere serialization-Struktur bereitstellt. ( im
Falle von xml wird hier ein neuer Tag aufgemacht )
s_container<ContainerTyp>: beschreibt eine Sequenz von Objekten mit
gleichem Typ. ContainerTyp wird hier verwendet um über value_type und
andere durch den Standard vorgesehene Typdefinitionen an den
eigentlichen Typ der Objekte zu kommen. Derzeit funktioniert dies nur
mit Typen die selbst wieder eine serialization-Struktur anbieten. An
dieser Einschränkung tüftle ich gerade. Vielleicht wird hier später bei
eingebauten Typen ein Wrapper vorgeschoben der diese Sturktur dann
bereitstellt.
Ein wichtiges Kriterium für dieses System war die Möglichkeit den Aufbau
eines XML-Dokumententyps über C++ Typen nachbauen zu können.
Die Aufgabe der serializable-Schablone ist es die statische Funktion
get_class_info() bereitzustellen die eine initialisierte class_info
Struktur zurückgibt. Darin befindet sich eine verarbeitete Variante der
obigen "ListeMitMetaTypen" und der Name der Klasse. Dazu muss
serializable die einzelnen Typlistenelemente (s_element, s_class .. )
zu meta_element, meta_class usw verarbeiten. Die meta_-Schablonen
bekommen einen weiteren Templateparameter, der für den zu
serialisierenden Typ steht, um get und set Methoden anbieten zu können.
Jede dieser instantierten meta_-Schablonen bietet 2 bis 3 init Methoden
an. Über die init Methode wird der Name der Variable, und der Zugriff
festgelegt. Es ist möglich beispielsweise einen get- und einen
set-Methodenpointer zu übergeben, oder einen Speicheroffset relativ zum
umgebenden Typ (auch hier muss serializable etwas Vorarbeit leisten).
Da dies serializeable aber nicht selbst festlegen kann muessen hier
Funktionen der serialization Struktur aufgerufen werden, die vom
Anwender hoffentlich implementiert wurden. Einerseits get_name um den
Namen der Klassse festzulegen, und init_member_list um die Liste der
instantierten meta_-Schablonen zu initialisieren.
Hierzu ein Beispiel:
<Window title="My Window">
<button name="OkButton" EventId="0">Ok</button>
<button name="CancelButton" EventId="1">Cancel</button>
</Window>
Zugehörige Klassenstruktur:
class Button
{
private:
int id;
std::string name, text;
public:
void setName( const std::string & n);
const std::string & getName() const;
struct serialization : public serializable<Button, mpl::vector<
s_element >
{
static const std::string get_name() const {return "button";}
template <size_t Offset, class MetaInfo>
static void set_member_list( MetaInfo& meta, size_t memory_offset)
{
field_nc<Offset+0>(meta ).init( "id",
memory_offset + MEMBER_OFFSET(Button,id) );
field_nc<Offset + 1>(meta ).init( "name",
&Button::setName,
&Button::getName );
field_nc<Offset + 2>( meta ).init( "text",
memory_offset + MEMBER_OFFSET( Button, text ) );
}
};
};
Auf die Attribute text und id wird direkt über den Speicheroffset
zugegriffen. Dieser wird aus dem durch memory_offset übergebenen Offset
der Klasse relativ zum eigentlich "Objektanfang" und dem Offset der
Variable in der Klasse berechent. ( Die Klasse koennte ja von einer
anderen verebt worden sein und sozusagen Teil eines größeren Objekts sein ).
Für das Attribut name wird stattdessen eine get und eine set Funktion
angeboten. Dies hat den Nachteil dass der serialisierer wohl eine
temporäres Objekt anlegen muss welches dann zum setzen übergeben wird.
Es gibt hierbei noch eine dritte Möglichkeit, wenn man nämlich einen
Set-Methodenpointer vom Typ ElementTyp & (ObjektTyp::*)() übergibt. Dann
kann beim Deserialisieren auch ohne ein temporäres Objekt gearbeitet werden.
Bei Window muss die Kontainer-Schablone verwendet werden:
class Window
{
private:
std::string title;
std::list<Button> buttons;
public:
struct serialization : public serializable<Window, mpl::vector<
s_element >
{
static const std::string get_name() const {return "window";}
template <size_t Offset, class MetaInfo>
static void set_member_list( MetaInfo& meta, size_t memory_offset)
{
field_nc<Offset + 0>(meta).init( "title",
memory_offset + MEMBER_OFFSET( Window, title ) );
field_nc<Offset + 1>(meta).init( "button",
memory_offset + MEMBER_OFFSET( Window, buttons),
&std::list<Button>::push_back,
&std::list<Button>::begin,
&std::list<Button>::end );
}
};
};
Mir sind bisher folgende Nachteile aufgefallen:
- Zyklische Sturkturen wurden in diesem Konzept noch gar nicht
behandelt... könnten und werden wohl aber noch eingebaut werden.
- Die Struktur der Serialisierung zwingt den Programmierer einen
bestimmten Klassenaufbau einzuhalten.
- Da in den meta_-Schablonen get, set und get_ref Methodenpointer
abgelegt werden, muss sich der Anwender an exakt diese Protoypen halten.
Man kann nicht von implizieter Konvertierung des Parameters oder des
Rückgabewerts profitieren.
Der bisherige Aufbau ist also eher komplex und teilweise unhandlich.
Ich richte mich mit dem Konzept an die Newsgroup, da ich Wege suche es
noch weiter zu verbessern. Den Quellcode der serialize Schablone und des
Xml-(De)Serialisierers könnte ich hier vöffentlichen, falls Interesse
besteht.
Grüsse
Andreas Pokorny
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Jan Langer Guest
|
Posted: Sun Dec 28, 2003 11:47 pm Post subject: Re: Serialisierungskonzept |
|
|
Andreas Pokorny wrote:
| Quote: | Ich beschäftige mich dieser Tage mit möglichst formatunabhängiger
(De)Serialisierug ( oder Persistenz ) von Objekten. Ziel war ein System
das vom Benutzer verwendet wird um formatfrei Elemente in Klassen zu
deklarieren die dann von dem jeweiligen Serialisierer verwendet werden
um die Daten auszulesen oder in neu erstellte Objekte zu schreiben.
Nachdem das System nun weitesgehnd funktionsfähig zu sein scheint und
der XML-Serialisierer funktioniert, kommen mir Zweifel ob es die Mühe
wert und ob das Konzept nicht gleichzeitig zu einschränkend und zu
komplex ist.
[...]
Ich richte mich mit dem Konzept an die Newsgroup, da ich Wege suche es
noch weiter zu verbessern. Den Quellcode der serialize Schablone und des
Xml-(De)Serialisierers könnte ich hier vöffentlichen, falls Interesse
besteht.
|
du koenntest dir auch die sich in der entwicklung befindliche boost
serialization library anschauen. da wird wohl das selbe gemacht wie du
es vorhast.
http://groups.yahoo.com/group/boost/files/seiralization13.zip
da brauchst du aber imho nen yahoo account.
jan
--
jan langer ... [email]jan (AT) langernetz (DOT) de[/email]
"pi ist genau drei"
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Marco Budde Guest
|
Posted: Mon Dec 29, 2003 10:32 am Post subject: Re: Serialisierungskonzept |
|
|
Andreas Pokorny wrote:
| Quote: | Der bisherige Aufbau ist also eher komplex und teilweise unhandlich.
Ich richte mich mit dem Konzept an die Newsgroup, da ich Wege suche es
noch weiter zu verbessern.
|
Du kannst Dir ja zum Vergleich mal die Konzepte im .NET Framework von
Microsoft anschauen.
Ich durfte die letzten Monate dieses Konzept in der Praxis erleben
und muß sagen, daß ich diese ganze Serialisierungskonzepte seither
für noch weniger sinnvoll erachte als vorher schon.
Das ganze wird sehr schnell total unübersichtlich, ist absolut langsam
und dauert vor allem von der Entwicklung her deutlich länger, als wenn
man manuelle Funktionen zu Speichern und Lesen schreiben würde.
cu, Marco
--
S: Minolta: Winkelsucher (VN), VC-9
E-Mail: mb-news-b<ät>linuxhaven.de
Deutsches Linux HOWTO Projekt: http://www.linuxhaven.de
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Andreas Pokorny Guest
|
Posted: Thu Jan 01, 2004 11:16 am Post subject: Re: Serialisierungskonzept |
|
|
Jan Langer wrote:
| Quote: | [...]
Ich richte mich mit dem Konzept an die Newsgroup, da ich Wege suche es
noch weiter zu verbessern. Den Quellcode der serialize Schablone und
des Xml-(De)Serialisierers könnte ich hier vöffentlichen, falls
Interesse besteht.
du koenntest dir auch die sich in der entwicklung befindliche boost
serialization library anschauen. da wird wohl das selbe gemacht wie du
es vorhast.
Leider nicht, dort ist es nicht möglich zu beeinflussen wie die |
Variablen in dem XML-Dokument abgelegt werden. So betrachtet ist mein
Ansatz eher ein "XML-Databinder" als eine Serialisierungsbibliothek, ich
wollte mir dadurch das Schreiben eigener SAX Routinen zum Einlesen von
XML Dokumenten sparen. Leider wird man aber von meinem Aufbau in eine
strengere Hierarchie gezwängt. Bei boost kann man dafür eine eigene
Load/Save- oder eine Serialisierungsmethode implementieren und darin den
Verlauf des Einlesen oder Schreibens zur Laufzeit beeinflussen.
Andreas Pokorny
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Robert Frunzke Guest
|
Posted: Tue Jan 06, 2004 5:58 pm Post subject: Re: Serialisierungskonzept |
|
|
| Quote: | Das ganze wird sehr schnell total unübersichtlich, ist absolut langsam
und dauert vor allem von der Entwicklung her deutlich länger, als wenn
man manuelle Funktionen zu Speichern und Lesen schreiben würde.
|
Die Erfahrung habe ich leider auch gemacht. Für ein Projekt benutze ich
z.B. ein einfaches Konzept mit Serialize und UnSerialize Methoden, und
ein kleines und einfaches Type-System und Versionen. Hab damit nur gute
Erfahrungen gemacht. Beispiel:
class Foo : public Serializable {
...
public:
virtual void Serialize( CSerializer &s ) {
s.SetVersion(1);
s.Put( dataxyz );
s.Put( datazzz );
s.BeginBucket();
pointerxyz->Serialize(s);
s.EndBucket();
}
virtual void UnSerialize( CUnSerializer &s ) {
if( s.GetVersion()==0 ) {
// version 0 lesen ..
} else if( s.GetVersion()==1 ) {
// version 4 lesen...
dataxyz = s.Get( CData::cdINT );
datazzz = s.Get( CData::cdFLOAT );
if( s.NextBucket() ) {
pointerxyz = new XYZ;
pointerxyz->UnSerialize(s);
s.EndBucket();
}
} else {
throw CFatalError( "Foo::UnSerialize() is not implemented
for version %d",s.GetVersion() );
}
}
};
CSerializer und CUnserializer müssen lediglich einen Stack (z.b. mit den
offsets in der Datei) besitzen um Daten hierarchisch lesen und schreiben
zu können, und müssen halt diverse Daten-Typen beherrschen. Daten können
on-the-fly gelesen und geschrieben werden - verbraucht damit also kaum
Speicher. Ein Umsetzung in einem XML-Format sollte problemlos möglich sein.
Gruß,
Robert
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Tue Jan 06, 2004 9:08 pm Post subject: Re: Serialisierungskonzept |
|
|
Robert Frunzke wrote:
| Quote: | Das ganze wird sehr schnell total unübersichtlich, ist absolut langsam
und dauert vor allem von der Entwicklung her deutlich länger, als wenn
man manuelle Funktionen zu Speichern und Lesen schreiben würde.
Die Erfahrung habe ich leider auch gemacht. Für ein Projekt benutze ich
z.B. ein einfaches Konzept mit Serialize und UnSerialize Methoden,
|
Ich frage mich gerade, ob ich der einzige Mensch auf dieser Welt bin,
der denkt, daß Serialisierung und Deserialisierung nicht symetrisch sind
Auch empfinde ich den Zwang, von einer Basisklasse ableiten zu
müssen als Einschränkung, die ich für unnötig halte.
Zur Asymetrie:
Während ich ein Objekt natürlich tausende mal serialisieren kann, möchte
ich doch beim Deserialisieren ein Objekt aus einem Datenstrom entstehen
lassen. Sprich, das natürlichste erscheint mir den Konstruktor für so
etwas zu benutzen. Hat auch noch den Vorteil, das die zu
deserialisierende Klasse keinen default c'tor benötigt. Das
Serialisieren implementiere ich auch als Funktion, die heißt bei mir
jedoch operator<<().
Zur benötigten Basisklasse:
Die Funktionalitäten zum schreiben bzw. lesen eines Objekts (c'tor und
operator<<()) bilden ein Protokoll. Wenn ich als erstes Element eines
Objekts ein Foo geschrieben habe, erwarte ich beim Lesen auch ein Foo
(Versionänderungen mal aussen vorgelassen). Mit einem Serializable kann
ich da nichts anfangen. Vielleicht übersehe ich auch etwas, aber wozu
die Basisklasse? Entweder die zu serialisierende Klasse hat die
Funktionen Serialize() und UnSerialize() oder nicht. Wenn ich
Klassenhierarchien serialiseren möchte, benötige ich spätestens beim
Deserialisieren sowieso eine factory.
Hier mein Beispiel ( Ohne Versionierung )
class Foo {
public:
Foo( CUnSerializer &s )
: dataxyz( s )
, dataxzz( s )
, pointerxyz( new XYZ(s) )
{
}
CSerializer& write( CSerializer& s ) const
{
return s << dataxyz << dataxzz << *pointerxyz;
}
};
CSerializer& operator<<(CSerializer& s, const Foo& foo) {
return foo.write(s);
}
Sieht natürlich einfacher aus, weil ich keine Versionierung habe
Durch implizite Konvertierungen (oh, ich höre schon die "Bäh, das macht
man nicht" Rufe des CUnSerializer Objekts in alle von der
Serialisierung unterstützten Basistypen (im Beispiel int und float)
bekommt man für alle member der Klasse die gleiche Syntax. Im Fall von
XYZ muß dieser Typ einen Konstrutor mit einem CUnSerializer als
Parameter besitzen.
Ich habe nun schon so oft diese Symetrie von Schreiben und Lesen (z.B.
operator<<() und operator>>() aus der Standardlibrary) gesehen und frage
mich ob das wirklich sinnvoll ist, oder nicht einfach nur Gewohnheit
bzw. Estetik.
Kommentare?
mfg Torsten
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
King Leo - Martin Oberzal Guest
|
Posted: Tue Jan 06, 2004 9:35 pm Post subject: Re: Serialisierungskonzept |
|
|
Torsten Robitzki wrote:
| Quote: | Ich frage mich gerade, ob ich der einzige Mensch auf dieser Welt bin,
der denkt, daß Serialisierung und Deserialisierung nicht symetrisch sind
Auch empfinde ich den Zwang, von einer Basisklasse ableiten zu
müssen als Einschränkung, die ich für unnötig halte.
Zur Asymetrie:
Während ich ein Objekt natürlich tausende mal serialisieren kann, möchte
ich doch beim Deserialisieren ein Objekt aus einem Datenstrom entstehen
lassen. Sprich, das natürlichste erscheint mir den Konstruktor für so
etwas zu benutzen. Hat auch noch den Vorteil, das die zu
deserialisierende Klasse keinen default c'tor benötigt. Das
Serialisieren implementiere ich auch als Funktion, die heißt bei mir
jedoch operator<<().
|
Und was machst du, falls die DeSerialisierung fehlschlägt? Eine Exception im
Konstruktor werfen sollte man ja nicht.
Bei der Symmetrischen Methode hast du einen default c'tor, und bei deiner
c'tor Methode hast du eine extra valid() Funktion.
Ich seh weder da noch dort einen Vorteil.
Gruß, Martin!
Ps:
Nicht dass ich mich jemals mit Serialisierung beschäftigt hätte...
--
Wenn man einen 17'' Monitor mit einem 2'' Display vergleicht, fragt
man sich schon, wo da an einem Mobiltelefon der technische
Fortschritt zu finden ist. Alexander Oberzalek
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Robert Frunzke Guest
|
Posted: Tue Jan 06, 2004 9:46 pm Post subject: Re: Serialisierungskonzept |
|
|
Das Beispiel hatte ich mal schnell zusammengeschrieben, das
Gesamt-Konzept hat Factories und es gibt keine Basisklasse Serializable
(war ne dumme Idee das dazuzudichten *g*) usw.
| Quote: | Zur Asymetrie:
Während ich ein Objekt natürlich tausende mal serialisieren kann, möchte
ich doch beim Deserialisieren ein Objekt aus einem Datenstrom entstehen
lassen. Sprich, das natürlichste erscheint mir den Konstruktor für so
etwas zu benutzen. Hat auch noch den Vorteil, das die zu
deserialisierende Klasse keinen default c'tor benötigt.
|
Ja, könnte man machen. Deserialisieren im Konstruktor hab ich aber
bewusst vermieden, um mich nicht mit Exceptions in Konstruktoren
abplagen zu müssen - irgendwo in der Mitte von "Exceptional C++" hab
ichs aufgegeben :)
Andererseits brauche ich sowieso meist einen default c'tor! Was willst
Du serialisieren, wenn Du es nie erstellen kannst ?
| Quote: | Hier mein Beispiel ( Ohne Versionierung )
class Foo {
public:
Foo( CUnSerializer &s )
: dataxyz( s )
, dataxzz( s )
, pointerxyz( new XYZ(s) )
{
}
CSerializer& write( CSerializer& s ) const
{
return s << dataxyz << dataxzz << *pointerxyz;
}
};
CSerializer& operator<<(CSerializer& s, const Foo& foo) {
return foo.write(s);
}
|
Bin mir nicht sicher, wie Du die Hierarchien implementieren möchtest ?
| Quote: | Sieht natürlich einfacher aus, weil ich keine Versionierung habe
Durch implizite Konvertierungen (oh, ich höre schon die "Bäh, das macht
man nicht" Rufe des CUnSerializer Objekts in alle von der
Serialisierung unterstützten Basistypen (im Beispiel int und float)
bekommt man für alle member der Klasse die gleiche Syntax. Im Fall von
XYZ muß dieser Typ einen Konstrutor mit einem CUnSerializer als
Parameter besitzen.
|
Implizite Typ-Konvertierungen sind ne schöne Sache. Dafür gibts bei mir
CData. Alle Typen die ich brauche können implizit in CData konvertiert
werden und vice-versa. Das verschlankt Serializer und UnSerializer
einigermaßen (das eigentliche Schreiben/Lesen muss natürlich wieder die
Datentypen kennen).
Ob man nun << oder eine Methode .Put() (oder wieauchimmer die heißt *g*)
benutzt halte ich für unwichtig. << ist eleganter, da geb ich Dir Recht.
Gruß,
Robert
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Tue Jan 06, 2004 10:07 pm Post subject: Re: Serialisierungskonzept |
|
|
King Leo - Martin Oberzalek wrote:
| Quote: | Torsten Robitzki wrote:
Ich frage mich gerade, ob ich der einzige Mensch auf dieser Welt bin,
der denkt, daß Serialisierung und Deserialisierung nicht symetrisch sind
Auch empfinde ich den Zwang, von einer Basisklasse ableiten zu
müssen als Einschränkung, die ich für unnötig halte.
Zur Asymetrie:
Während ich ein Objekt natürlich tausende mal serialisieren kann, möchte
ich doch beim Deserialisieren ein Objekt aus einem Datenstrom entstehen
lassen. Sprich, das natürlichste erscheint mir den Konstruktor für so
etwas zu benutzen. Hat auch noch den Vorteil, das die zu
deserialisierende Klasse keinen default c'tor benötigt. Das
Serialisieren implementiere ich auch als Funktion, die heißt bei mir
jedoch operator<<().
Und was machst du, falls die DeSerialisierung fehlschlägt? Eine Exception im
Konstruktor werfen sollte man ja nicht.
|
Das hast Du evtl. mit dem Destruktor verwechselt. Im Konstruktor sollte
man (muß man meiner Meinung nach sogar) eine Ausnahme werfen, wenn man
es nicht schaft, ein Objekt zu konstruieren, das danach in einem
benutzbaren Zustand ist. Da hat die Ausnahme im Konstruktor gegenüber
der Ausnahme in der Mitte der Deserialisierungfunktion noch den Vorteil,
das es bei der Ausnahme im Konstruktor schlicht und einfach kein Objekt
gibt, das in einem unbenutzbaren Zustand sein kann (google :
Invarianten). Habe ich ein A, das ein B, welches ein C, welches wiederum
ein D enthält und tritt dann beim Deserialisieren von D eine Fehler auf
(z.B. Abbriss der Netzwerkverbindung) so tritt auch eine Ausnahme bei
der Konstruktion von C, B und A auf. Damit ist der gesammte Versuch, ein
A vom Datenstrom zu lesen fehlgeschlagen, ergo habe ich kein A.
Natürlich könnte man das Lesen über Funktionen auch exception save
machen. Dafür müste man aber eine Menge von Kopien anlegen um sicher zu
stellen, das ein Objekt, bei dessen Deserialisierung ein Fehler auftritt
unverändert bleibt:
std::istream& A::read(std::istream& i)
{
A tmp(*this);
i >> tmp.b; // hier könnte eine Ausnahme auftreten
swap(tmp); // hier kann keine Ausnahme auftreten
}
| Quote: | Bei der Symmetrischen Methode hast du einen default c'tor, und bei deiner
c'tor Methode hast du eine extra valid() Funktion.
|
Die einfachste Methode Fehler zu vermeiden ist es, nicht zuzulassen das
es Objekte gibt, die in einem Zombie-Zustand sind. Dazu sind Ausnahmen
in Konstruktoren hervorragend geeignet. Hat man keine Objekte, die je in
einen ungültigen Zustand geraten können, so brauch man auch keine
valid() Funktion.
mfg Torsten
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Markus Schaaf Guest
|
Posted: Wed Jan 07, 2004 12:35 am Post subject: Re: Serialisierungskonzept |
|
|
"King Leo - Martin Oberzalek" <kingleo (AT) gmx (DOT) at> schrieb:
| Quote: | Torsten Robitzki wrote:
Ich frage mich gerade, ob ich der einzige Mensch auf dieser Welt bin,
der denkt, daß Serialisierung und Deserialisierung nicht symetrisch sind
Auch empfinde ich den Zwang, von einer Basisklasse ableiten zu
müssen als Einschränkung, die ich für unnötig halte.
Zur Asymetrie:
Während ich ein Objekt natürlich tausende mal serialisieren kann, möchte
ich doch beim Deserialisieren ein Objekt aus einem Datenstrom entstehen
lassen. Sprich, das natürlichste erscheint mir den Konstruktor für so
etwas zu benutzen. Hat auch noch den Vorteil, das die zu
deserialisierende Klasse keinen default c'tor benötigt. Das
Serialisieren implementiere ich auch als Funktion, die heißt bei mir
jedoch operator<<().
Und was machst du, falls die DeSerialisierung fehlschlägt? Eine Exception im
Konstruktor werfen sollte man ja nicht.
|
Im Gegensatz: dieses Szenario ist geradezu ein Paradebeispiel für den
sinnvollen Einsatz einer Exception.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Wed Jan 07, 2004 10:26 pm Post subject: Re: Serialisierungskonzept |
|
|
Robert Frunzke wrote:
| Quote: | Zur Asymetrie:
snip
Ja, könnte man machen. Deserialisieren im Konstruktor hab ich aber
bewusst vermieden, um mich nicht mit Exceptions in Konstruktoren
abplagen zu müssen - irgendwo in der Mitte von "Exceptional C++" hab
ichs aufgegeben :)
Andererseits brauche ich sowieso meist einen default c'tor! Was willst
Du serialisieren, wenn Du es nie erstellen kannst ?
|
Ich habe mal eben über mein Spaßprojekt geguckt. Da haben ca. 50% der
Klassen eine default c'tor. Einigen könnte man vielleicht auch noch
einen default c'tor spendieren aber bei sehr vielen gibt es keinen
sinnvollen default c'tor. Eine Klasse, die keinen default c'tor hat,
kann ja trotz dem eine Menge von sinnvollen und nützlichen Konstruktoren
haben. Z.B. auch um ein Objekt mit Daten zu füllen (wobei Datenklassen
in der Tat häufig einen default c'tor haben).
| Quote: |
Hier mein Beispiel ( Ohne Versionierung ) |
| Quote: | Bin mir nicht sicher, wie Du die Hierarchien implementieren möchtest ?
|
class reader
{
....
template<class Base>
Base* read_reference();
};
class writer
{
....
template<class Base>
writer& write_reference(const Base*, const char* name);
};
Beim schreiben eines polymorphen Objektes, muß man den Namen (oder
Schlüssel) unter dem die Klasse des Objektes bei einer Factory
registriert wurde mit angeben. Anhand dieses Schlüssels wird dann beim
Deserialisieren eine Funktion aufgerufen, die dann eine Instanz einer
konkreten Klasse erzeugt.
struct Base {
virtual ~Base() {}
virtual const char* name() const = 0;
virtual ipc::writer& write(icp::writer&) const = 0;
};
ipc::writer& operator<<(ipc::writer out, const Base& b) {
return b.write(out);
}
Schreiben:
ipc::writer out(..);
Base* b = ...;
out.write_reference(b, b->name());
Lesen
ipc::reader in(..);
Base* b = in.read_reference<Base>();
mfg Torsten
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|