dynamisch erzeugte Objekte zerstören
-
ich habe ein größeres Projekt mit mehreren Forms und Klassen. Ich versuche immer Variablen die ich in mehreren Methoden/Ereignissen brauche als private in die Header der Formklasse zu schreiben. Bei dynanmischen Objekten deklarier ich dort auch mein Objekt also zB:
class TForm1 : public TForm { private: int zahl; TStringList strl; public: TF_HO(TComponent* Owner); int Get_zahl(); }; int TForm1::Get_zahl() {return zahl}
initialisiere im Konstruktor der Form mit NULL und erzeuge das Objekt an entsprechender Stelle zB über Button oder auch im Konstruktor der Form:
TF_HO::TF_HO(TComponent* Owner) : TForm(Owner), strl(NULL) {strl = new TStringList();}
Frage nun:
1. ist das ok so? Wird das so gemacht?
2. falls ich das Objekt gleich im Konstruktor erzeugen möchte, kann ich das doch eigentlich gleich in der Konstruktorliste machen oder? alsoTF_HO::TF_HO(TComponent* Owner) : TForm(Owner), strl(new TStringList()) {}
. Wenn ja, dann kann man das ja auch in der Initialisierungsliste von Ereignissen machen also zB über einen Button:
void __fastcall TF_HO::Button1(TObject *Sender) : strl(new TStringList() {}
aber ich denke mal, das geht nicht
3. Muss ich die dyn. erzeugten Objekte wieder mit delete zerstören? Und wenn wo am besten? Oder macht das der Destruktor automatisch?
-
Hallo,
Wenn du diese StringListe auf jedem Fall brauchst macht es Sinn die im Konstruktor zu erstellen. Du mußt dieses Objekt natürlich im Destruktor selbst mit delete löschen.
Das brauchst du dann nicht zu tun, wenn du dein Objekt in einem Smartpointer kapselst. Solange du das Objekt nur intern in deiner Klasse brauchst und nie nach außen übergeben musst ist auto_ptr ausreichend.
Wenn du das Objekt irgendwie verteilen musst, wäre boost::shared_ptr eine gute Wahl.
Wenn man das Objekt manchmal nicht braucht kann man den Zeiger auch erst im Konstruktor auf 0 setzten und dann bei Bedarf erstellen. Einfach immer vor Gebrauch auf 0 testen und erstellen wenn nötig. Löschen muss man natürlich trotzdem.
Die Klammern hinter TStringList beim new sind unnötig.
-
Hallo
1. Grundsätzlich ist das in Ordnung. Allerdings gibt es keinen Grund, strl in der Initialisierungsliste erst mit NULL zu initialisieren, und dann im Konstruktor gleich wieder einem neuen Wert zuzuweisen. Das Zuweisen kannst du auch gleich in der Initialisierungsliste machen
TF_HO::TF_HO(TComponent* Owner) : TForm(Owner), strl(new TStringList()) {}
Das NULL-Initialisieren brauchst du nur machen, wenn der eigentliche Wert erst nach dem Konstruktor, z.B. im einem Button-Events, zugewiesen wird.
2. Ja, du must manuell mit new erzeugte Objekte auch wieder mit delete löschen. (Ausnahmen gibt es natürlich, z.B. VCL-Komponenten die mit einem Parent erzeugt werden). Spätestens der Destruktor des Forms sollte das delete ausführen.
bis bald
akari
-
wenn ich den Konstruktor einer Formklasse erzeugen lasse bekomm ich einen Fehler:
[C++ Fehler] Messgeraet.h(23): E2113 Virtuelle Funktion 'TF_Messgeraet::~TF_Messgeraet()' verursacht Konflikte mit der Basisklasse 'TForm'
ich wollte dort meine Objekte mit delete zerstören.
-
Hallo
Du meinst nicht den Konstruktor, sondern den Destruktor.
Ich vermute mal, das du __fastcall vergessen hast. Bei allen Klassen die von VCL-Klassen abgeleitet sind, müßen Kon- und Destruktor mit __fastcall versehen werden.// Deklaration __fastcall ~TF_Messgeraet(); // Implementation __fastcall TF_Messgeraet::~TF_Messgeraet() { delete ...; }
bis bald
akari
-
ja ich meinte den Destruktor. Du hattest recht. Das fastcall hatte ich vergessen. Soweit ich weiss bewirkt dies, dass in Registern gespeichert wird. Macht es Sinn alle eigenen Funktionen auch mit fastcall zu versehen?
-
rudpower schrieb:
Macht es Sinn alle eigenen Funktionen auch mit fastcall zu versehen?
Nein (-> premature optimization).