Wie TSTringList in eigene Klasse einbinden?
-
Arno schrieb:
MyClass.cpp
TFlugzeug::~TFlugzeug () { delete &slMyList; }Sollte wohl eher
TFlugzeug::~TFlugzeug () { delete slMyList; }heißen, ansonsten könntest du früher oder später eine Zugriffsverletzung bekommen und die zu lokalisieren kan laaaaa...aaaange dauern.
-
Nee, sorry.
Mit:
TFlugzeug::~TFlugzeug () { delete slMyList; }bekomme ich sofort eine Zugriffsverletzung.
-
Bitte unterschiedliche Klassennamen ignorieren, bin da etwas durcheinander gekommen.

-
Arno schrieb:
Nee, sorry.
Mit:
TFlugzeug::~TFlugzeug () { delete slMyList; }bekomme ich sofort eine Zugriffsverletzung.
Das sollte nicht sein, denn so werden üblcherweise Objekte zerstört.
-
Muss Dir recht geben, etwas ist da schief gelaufen.
Ich wollte einen Vektor mit dieser Klasse füllen, dabei ist mir aufgefallen das alle Elemente des Vektors auf die selbe StringList zugreifen.
-
Sorry dass ich dieses Thema noch mal aufwärme.
Ich komm hier nicht weiter. Wie schon beschrieben habe ich die Klasse jetzt zwar eingebunden, aber wenn ich mit dieser Klasse einen Vektor initialisiere (bin nicht sicher ob das der richtige Ausdruck ist, ich meine den Vektor mit dieser Klasse über "push_back" fülle) greifen alle Elemente des Vektor auf ein und die selbe StringList zu.
Ist es möglich dass es am Kopierkonstruktor liegt?
Bin über jede Hilfe dankbar.
Gruß Arno
-
Hallo
- push_back ist keine Intialisierung mehr.
- sehe ich aus den bestehenden Posts nicht, wie da nun ein vector mitspielt. Also poste bitte nochmal aktuellen Code, der den Zsuammenhang Klasse-StringList-vector darstellt, insbesondere den Kopierkonstruktor.
bis bald
akari
-
Hallo Akari,
den Kopierkonstruktor wollte ich eigentlich auf diese Weise implementieren:
//MyClass.h private: TMyClass(const TMyClass&) {}Das quitiert mein Builder 6 aber mit einer Fehlermeldung, da auf die Funktion nicht zugegriffen werden kann. Was ich eigentlich auch damit bezwecken will.
//MyClass.h class TMyClass { private: AnsiString asKennung; TStringList *slEreignisse; public: TFlugzeug (); ~TFlugzeug (); void SetKennung (AnsiString Kennung); AnsiString GetKennung (void); void AddLine (AnsiString Line); AnsiString GetText (void);// MyClass.cpp #include <System.hpp> #include <Classes.hpp> #include "MyClass.h" TMyClass::TMyClass () { slEreignisse = new TStringList; } //--------------------------------------------------------------------------- void TMyClass::SetKennung (AnsiString Kennung) { asKennung = Kennung; } //--------------------------------------------------------------------------- AnsiString TMyClass::GetKennung (void) { return asKennung; } //--------------------------------------------------------------------------- void TMyClass::AddLine (AnsiString Line) { slEreignisse->Add(Line); } //--------------------------------------------------------------------------- AnsiString TMyClass::GetText (void) { return slEreignisse->Text; } //---------------------------------------------------------------------------In Meinem Programm itteriere ich durch ein Stück einer Datei, die ersten Zeichen sind jeweils eine Kennung, dahinter kommt ein Ereigniss.
(Den folgenden Quellcode hab ich etwas verkürzt ausserdem ist er teilweise in Pseudocode)// MyApp.cpp vector <TMyClass> MyClass; // ist global definiert . . solange bis Sektionsende erreicht: { TMyClass *MyClassDummy = new TMyClass; MyClassDummy->Kennung(Kennung_aus_Datei) // wird mit SubString zerpflügt MyClass.push_back(*MyClassDummy); delete MyClassDummy; } . .Ich hoffe es kommt einigermassen rüber was ich damit vorhabe.
Es geht schlichtweg darum, das ich für jede Kennung die in der Datei vorkommt, eine "StringList" bräuchte.
Beim Debuggen ist mir dann eben aufgefallen, dass der Standartkonstruktor nur ein einziges mal aufgerufen wird.
-
Hallo
und warum wunderst du dich über die Fehlermeldung, wenn du den Kopierkonstruktor der Klasse private machst?
Denn schon allein vector braucht den Kopier-Konstruktor als public.bis bald
akari
-
Weil es in der Anleitung auf dieser Seite so beschrieben ist:
http://www.red-inferno.de/cplusplus/basic/OOP/techniques_extensions/main.htm
Private Konstruktoren und Destruktoren und private Operatoren
Wird eine Klasse deklariert, die keinen eigenen Konstruktor besitzt, dann werden zwei Konstruktoren automatisch hinzugefügt: Der Standardkonstruktor und der Kopierkonstruktor. Besitzt die Klasse hingegen einen eigenen Konstruktor, dann wird auf jeden Fall eine Kopierkonstruktor hinzugefügt. Letzterer lässt sich, wie bereits zuvor gezeigt wurde, überschreiben, um u.U. genau zu bestimmen, wie die Member kopiert werden. Ist es jedoch hingegen überhaupt nicht erwünscht, dass von einer Klasse Kopien erstellt werden, dann sollte der Kopierkonstruktor einfach als 'private' deklariert werden:
class CCopysafe { private: CCopysafe(const CCopysafe&) {} };Bin ich komplett auf dem Holzweg?
-
Hallo
soweit sogut... aber wie ich bereits geschrieben habe, wird durch vector<TMyClass> zwingend ein public Ctor benötigt. Denn vector muß bei Größenänderungen gegenenfalls die Elemente umkopieren.
Das könntest du umgehen, indem du nur Pointer in den vector legst : vector<TMyClass*>. Dann bist du ganz allein für die Speicherverwaltung der Instanzen zuständig, aber da jetzt die Elemente nur Pointer sind (und diese automatisch kopiert werden können), brauchst du für die Klasse an sich keinen zugänglichen Ctor.
bis bald
akari
-
hmm, selbst den Speicherverwalten, das trau ich mir noch nicht wirklich zu.
Wie könnte ich es denn sonst noch bewerkstelligen dass ich für jedes Vektorelement eine eigene StringList bekomme?
-
Hallo
es geht nicht um die StringList. Das Problem ist allgemeiner : Du kannst in die Standard-Container nur kopierbare Elemente reinpacken.
Du hast also diese Möglichkeiten :
- Kopierkonstruktor public machen
- Pointer verwenden
- auf vector verzichten und mit einen selber allokiertem Array arbeiten. Ist aber auch das schwierigste, fehleranfälligste und C-mäßigste.bis bald
akari
-
Ursprünglich waren die Konstruktoren ja public, aber da hatte ich eben das Problem, dass alle Vektorelemente ein und die selbe StringList benutzten und eben nicht jedes Vektorelement seine eigene StringList hatte.
Mein Code sieht im Moment so aus wie ich ihn heute gepostet habe, mit dem privaten Kopierkonstruktor kann ich es ja nicht compilieren.
-
Hallo
Das liegt daran, das du die Aufgabe des kopier-Konstruktors nicht verstanden hast. Denn genau zur Lösung dieses Problems ist der da!
Bei dir sollte der so aussehenpublic : TMyClass(const TMyClass& source) { asKennung = source.asKennung; slEreignisse = new TStringList; slEreignisse->Assign(source.slEreignisse); }Denn ohne diesen wird vom Kompiler der Standard-Ctor eigesetzt. Und dieser kopiert einfach die Elemente... bei dir u.a. den Pointer auf die StringList.
Mit der Anpassung wird aber jetzt stattdessen auch beim Kopieren eine neue StringList erstellt und die Werte (nicht die Instanz) der alten übernommen. Und schon hast du keine Probleme mehr mit public Ctor und vector.Übrigens : Die StringList sollte natürlich im Destruktor auch wieder gelöscht werden.
bis bald
akari
-
Vielen Dank Akari.
Kannst Du mir evtl. bitte ein Buch empfehlen wo genau solche Dinge erklärt werden?
Edit: Ein Web-Tutorial würd auch schon reichen.
Hab einige C++ Bücher gelesen, aber Assign tauchte da nirgends auf.
gruß Arno
-
Hallo
Bücherlisten findest du über die Suche oder über den Link Bücher im Menü oben rechts auf dieser Seite. Für die C++ Grundlagen, auch was OOP betrift, kannst du dir auch so ein Tutorial anschauen.
Übrigens hatte ich angenommen du wolltest unbedingt die Kopierbarkeit deiner Klasse aus Konzeptgründen verhindern. Deshalb kamm der Vorschlag mit dem richtigen Ctor so spät

/Edit : Und Assign ist eine Methode der Klasse TStringList, die findest du in der BCB-Hilfe.
bis bald
akari