Also hier meine Klasse:
Code
Hier speichere ich sie ab.
Und beim Laden bricht das Programm unschön ab.
Ich hoffe auf die Kompetenz des Forums.
Du bist in Begriff, Forum64 zu verlassen, um auf die folgende Adresse weitergeleitet zu werden:
Bitte beachte, dass wir für den Inhalt der Zielseite nicht verantwortlich sind und unsere Datenschutzbestimmungen dort keine Anwendung finden.
letzter Beitrag von Zirias/Excess am
Also hier meine Klasse:
Hier speichere ich sie ab.
Und beim Laden bricht das Programm unschön ab.
Ich hoffe auf die Kompetenz des Forums.
std::string Strings kann man nicht einfach beschreiben wie POD (Plain Old Data).
Da Strings intern selber Pointer usw besitzen (um z.B. weiteren Speicher zu allokieren) kann man da nicht einfach wild drüberkopieren.
Das du brauchst ist eine Methode Serialize() bzw. Deserializte()
Das kann c++ leider nicht selber. (mit boost ginge das)
Die Länge zu Beginn würde ich einfach so schreiben/lesen:
Aber der Rest, den Speicherbereich, den das Objekt belegt, abzuspeichern, funktioniert wahrscheinlich trotzdem nicht. String und QList benutzen intern Zeiger. Beim Abspeichern werden die Speicherbereiche, auf die die "internen" Zeiger zeigen nicht mit abgespeichert und nach dem Einlesen sind deshalb dort keine Daten.
Edit: was Tulan auch schon schrieb...
Soweit ich weiß sind die Strukturen ohne Zeiger intern der Klasse mit rel. Zeigern realisiert.
Ja, ich möchte den alten geladenen Klassenblock auf einen Dummy mit gleicher Größe schreiben.
Bei einer Klasse mit konstanter Klassengröße ist es übrigens kein Problem, das läuft ganz gut.
Du könntest aber auch mit einem streaming operator direkt in das File bzw. direkt vom File streamen.
Hier gibt es eine Diskussion:
http://www.cplusplus.com/forum/beginner/49924/
Ich wüsste nicht, dass es in C++ so etwas wie relative Zeiger gibt. Aber egal was für Zeiger das sind, wenn du die Größe eines Objekts bestimmts, ist da nicht die Größe des Speicherbereiches dabei, auf den ein Zeiger des Objekts zeigt.
Bei einem Objekt mit einfachen Datentypen kann das funktionieren. Das stimmt.
Bei einer Klasse mit konstanter Klassengröße ist es übrigens kein Problem, das läuft ganz gut.
Man kann nicht einfach wild ein "memcopy" in einen std::string machen.
string hat zb. append methoden, die den internen Speicher bei Bedarf erweitern. Da passieren new (mallocs) intern.
Das geht nur bei POD (int, long, double, ....) bei nicht komplexen Datentypen.
Schau dir bitte dieses Beispiel mal an:
http://www.cplusplus.com/forum/beginner/49924/#msg271283
Da ist das mit dem streamen ganz schön gemacht.
Die std::string programmiert haben, die werden ja nicht so besoffen gewesen sein, einen Zeiger außerhalb der Klasse zu erlauben. Nein, wenn ich die Klasse abspeicher, dann sehe ich in der Datei dass std::string mit der Klasse abgespeichert ist.
Zeiger, die außerhalb der Klasse zeigen sehe ich nicht.
Und was da an Code für den Konstruktor mit der Klasse abgespeichert wird, ist mir egal, weil der nie wieder aufgerufen wird.
Also zurück zu meiner Frage: Wie baue ich ein Objekt der gewünschten Größe damit ich da die Klasse wieder reinlesen kann (Die geschriebene Klasse ist im Anhang.)
Der Antwort aus Beitrag #2 ist eigentlich nichts hinzuzufügen.
VM: Du versuchst hier Dinge mit C++ zu tun, wie sie BIF mit dem Basic-Interpreter anstellt. Lass das sein. Und lern Grundlagen, z.B. den Unterschied zwischen Objekten und Klassen. Oder warum man dieses Objektorientierungs-Zeugs überhaupt macht, oder weshalb direkter Speicherzugriff auf ein Objekt von außen dieser Idee zuwiderläuft.
Ich sehe gerade die verwendest auch noch QList<metadatablock> list;
Bist also im QT Framework unterwegs:
ähnlicher Ansatz wie bei STL.
https://stackoverflow.com/ques…679/serialization-with-qt
Statt std::string würde ich aber dann QString verwenden, das ist in QT üblich.
Nein, so geht das nicht. Der eigentliche String wird ja nicht direkt im std::string Objekt gespeichert. Das ist ja nur eine Art Interface um mit den String Daten zu arbeiten. Der eigentlich String ist in einem dynamisch allokierten Speicherblock, den die std::string Klasse verwaltet.
Wie oben bereits erwähnt, man kann in C++ nicht einfach ein Objekt mal eben so rausschreiben. Dafür braucht man spezielle Serialisierung/Deserialisierung und dazu braucht man dann wieder Information über die Klassen die man schreiben/lesen will. Es kann ja z.b. auch ein std::vector vorkommen, der dann wieder ein Objekt enthält, d.h. das Problem ist meist nur rekursiv zu lösen.
Siehe: https://de.wikipedia.org/wiki/Serialisierung
Mir widert es an << >> zu überladen.
Notfalls programmiere ich ein bißchen um, daß die Größe konstant bleibt. Dann müßte ich mir keine Sorgen mehr machen.
@Mac Bacon Destruktive Kritik mag ich nicht.
Nein, so geht das nicht. Der eigentliche String wird ja nicht direkt im std::string Objekt gespeichert. Das ist ja nur eine Art Interface um mit den String Daten zu arbeiten. Der eigentlich String ist in einem dynamisch allokierten Speicherblock, den die std::string Klasse verwaltet.
Wie oben bereits erwähnt, man kann in C++ nicht einfach ein Objekt mal eben so rausschreiben. Dafür braucht man spezielle Serialisierung/Deserialisierung und dazu braucht man dann wieder Information über die Klassen die man schreiben/lesen will. Es kann ja z.b. auch ein std::vector vorkommen, der dann wieder ein Objekt enthält, d.h. das Problem ist meist nur rekursiv zu lösen.
Siehe: https://de.wikipedia.org/wiki/Serialisierung
"Der eigentlich String ist in einem dynamisch allokierten Speicherblock, den die std::string Klasse verwaltet"
Nein! Der String ist in der Klasse und wird auch ordentlich abgespeichert. Das kannst Du daran sehen, daß in der Datei die Zeichenkette "mistus" vorkommt. "mistus" steht da im string projectname.
Ich frage mich nur, ob die c++ Hersteller nüchtern genug waren am Klassenkopf die relativen Zeiger zu hinterlegen. Und der Kopf kann mit der class-Definition verstanden werden.
@Mac Bacon Destruktive Kritik mag ich nicht.
"Lern Grundlagen" ist das Konstruktivste, was man in diesem Fall sagen kann. Dass Dir das nicht gefällt, ändert daran nichts.
Ich weiß nicht. Vielleicht kommt mir noch die zündende Idee.
Oder jemandem von Euch.
Also durch rel. Zeiger innerhalb der Klasse und der Klassenkopf, der relativ auf die Funktionszeiger und Datenzeiger verweist, brauche ich mir nur dann Gedanken machen, wenn sie außerhalb der Klasse zeigen. Ich brauche eigentlich nur einen Block passender Größe, die komplette Klasse aus der Datei darein ziehen und dann den Block als Klasse umzuschreiben.
Also wie baue ich mir einen Speicherblock mit passender Größe zum Überschreiben?
Wie lasse ich diesen Speicherblock als entsprechende Klasse interpretieren?
Nein! Der String ist in der Klasse und wird auch ordentlich abgespeichert. Das kannst Du daran sehen, daß in der Datei die Zeichenkette "mistus" vorkommt. "mistus" steht da im string projectname.
Nein, das ist eher Zufall. Der String hat Anfangs (nach dem Konstruieren) eine gewisse Größe, daher geht sich das wohl zufällig aus.
Praxisbeispiel: In einen String kannst du, wenn du lustig bist, 1GB an Daten reinspeichern, wenn der Rechner das erlaubt.
Deswegen hat aber nicht ein Objekt deiner Klasse von Haus aus 1GB groß. Wo werden die 1GB dann wohl gespeichert? Richtig, auf dem Heap!
Und wie speichert man etwas auf dem Heap. Richtig mit new. Und was bekommt man da zurück? Richtig einen Pointer.
In C++ gibt es keine rel. Zeiger, sondern nur Zeiger.
"Der eigentlich String ist in einem dynamisch allokierten Speicherblock, den die std::string Klasse verwaltet"
Nein! Der String ist in der Klasse und wird auch ordentlich abgespeichert. Das kannst Du daran sehen, daß in der Datei die Zeichenkette "mistus" vorkommt. "mistus" steht da im string projectname.
Doch. Probiers aus:
Beide Objekte sind hier (VisualStudio 2015) gleich groß. Jeweils 28 Bytes
Mist verfluchter. Es stimmt. Haue ich ein Megabyte in einen std::string, dann ist der nicht mehr in der Klasse.
Ich hätte c++ anders programmiert, aber es ist eben so, wie es ist.
Gut, dann muß ich doch << und >> überladen. Das ist unglaublich viel Arbeit. Leider.
Nein! Der String ist in der Klasse und wird auch ordentlich abgespeichert. Das kannst Du daran sehen, daß in der Datei die Zeichenkette "mistus" vorkommt. "mistus" steht da im string projectname.
Du hast wohl den eigentlichen String versehntlich mit abgespeichert weil der Heapallokator einfach die Blöcke nebeneinander platziert hat. Das kann passieren, schliesslich ist das u.U. alles zufällig nebeneinander im Speicher, aber darauf kann man sich nicht verlassen.