![]() |
Handling von Objekten (vom Typ TObject)
Hey,
so, neue Frage, neuer Thread ;-) Ich beschäftige mich zur Zeit ein bisschen mit der Klasse TObject. Ich weiss jedoch leider noch nicht so recht wie genau man mit Objekten umgeht. Habe schon ein Tutorial gelesen, aber scheinbar mache ich hin und wieder etwas falsch, weil sich bei mir desöfteren Zugriffsverletzungen ereignen. Unklar ist mir z.B. wann ich
Delphi-Quellcode:
benutze und wann ich einfach ohne oben angegebene Zeile
Obj := TObject.Create;
Delphi-Quellcode:
verwende.
Obj := dummyFunction(getObj(Param));
Ein paar grundlegende Infos wären super! Danke schonmal! :-) |
Re: Handling von Objekten (vom Typ TObject)
Moin Christian,
im ersten Falle erzeugst Du das Objekt, und die Variable bekommt dann die Referenz auf die erzeugte Instanz, damit Du damit arbeiten kannst. Mit dem zweiten Fall kann ich nichts anfangen :gruebel: |
Re: Handling von Objekten (vom Typ TObject)
TObject ist die Mutter aller Klassen. D.h. jede Klasse in Delphi erbt von ihr.
Delphi-Quellcode:
Erzeugt eine neue Instanz
Obj := TObject.Create;
|
Re: Handling von Objekten (vom Typ TObject)
Okay, ein anderes Beispiel ;-)
Delphi-Quellcode:
Erstens wurde mir gesagt, dass ich TAuto.Create; nicht ausführen muss, zweitens, dass ich es in der zweiten Zeile wieder überschreibe und drittens bekomme ich bei tempAuto.Free; eine Zugriffsverletzung.
var tempAuto : TAuto;
begin tempAuto := TAuto.Create; tempAuto := autoSammlung.GetAutoByName('Opel'); tempAuto.Free; Zu den Punkten: 1.) Warum muss ich es nicht immer ausführen, wenn es doch "die Mutter aller Klassen" ist? 2.) Warum überschreibe ich tempAuto hier? Ich dachte ich hätte über Create die Instanz erstellt und würde ihr in der zweiten Zeile einfach ein Objekt zuweisen. 3.) Warum kann ich das Objekt auf diese Weise nicht einfach freigeben? So, das sind jetzt erstmal ein paar Fragen ;-) |
Re: Handling von Objekten (vom Typ TObject)
Wie schon oben gesagt, mit TObject.Create erzeugst Du eine neue Instanz - wenn Du das dreimal machst, hast Du am Ende drei eigenständige Objekte. Von denen muss auch jedes am Ende wieder abgeräumt werden (mittels FreeAndNil() oder TObject.Free, je nachdem, mein Tipp dazu: Verwende wo es geht FreeAndnil).
Der zweite Fall soll - vermute ich mal - das Weiterreichen einer Instanz symbolisieren. Dabei wird kein neues Objekt erzeugt, sondern nur eine Art Verweis auf ein bereits existierendes Objekt "nach draussen gereicht". Dieser Verweis, auch Pointer genannt, ermöglicht es Dir, von praktisch überall her auf das Objekt zuzugreifen. Ganz wichtig: Wenn Du mit diesen Verweisen arbeitest, musst Du sehr genau hinschauen, wer das Objekt am Ende wieder freigeben darf! Wenn das Objekt freigegeben wird, hat das keine Auswirkungen auf den Pointer, jedoch wird ein Zugriff über den Pointer auf das bereits abgeräumte Objekt meist mit einer Zugriffsverletzung "belohnt". Je nach Programm kann auch zuerst *anscheinend* alles glatt gehen, aber im Speicher kann dabei ziemliches Chaos angerichtet werden, was früher oder später das Programm zum Absturz bringt - oder zumindest zu seltsamem Verhalten bringt. Eine überall gültige Regel, welche Seite das Objekt, auf das der Pointer zeigt, wieder freigeben darf, gibt es nicht. In der Regel sagt man aber, wer es angelegt hat, sollte es auch wieder abräumen. Ausnahmen sind zum Beispiel Objekte, die zwar "auf der einen Seite" erzeugt werden, dann aber nur auf der "anderen Seite" benutzt werden. Hier macht es Sinn, das Objekt dann auch auf "der anderen Seite" abzuräumen wenn es nicht mehr benötigt wird. //EDIT: Roter Kasten :) Nachtrag: Ohne TAuto zu kennen, können diese Fragen nicht beantwortet werden, da die Antworten von der Implementation von TAuto abhängen. |
Re: Handling von Objekten (vom Typ TObject)
Zitat:
Zitat:
Zitat:
|
Re: Handling von Objekten (vom Typ TObject)
Zitat:
|
Re: Handling von Objekten (vom Typ TObject)
Moin Zusammen,
und um das von den anderen schon gesagte noch zu ergänzen: Um solche Probleme zu umgehen, sollte man nie Objekte als Rückgabewert einer Funktion verwenden, da dann immer das Problem besteht, die Freigabe korrekt zu positionieren. So wäre es übersichtlicher:
Delphi-Quellcode:
Es gibt zwar auch Methoden, die ein Objekt zurückgeben (z.B. TListView.Add gibt ein Objekt vom Typ TListItem zurück), aber in diesem Falle verwaltet auch die Klasse (hier TListView) selber die Objekte (TListItem).
var
tempAuto : TAuto; begin tempAuto := TAuto.Create; try // Das Objekt, bzw. die Instanz mit Daten füllen autosammlung.GetAutoByName('Opel',tempAuto); // mit dem Objekt (tempAuto) arbeiten //... finally tempAuto.Free; // oder FreeAndNil(tempAuto); end; end; // So könnte dann die Methode deklariert werden. // Statt eines Results vom Typ TAuto, wird eine Instanz von TAuto übergeben procedure TAutoSammlung.GetAutoByName(const AsTyp : string;const AResult : TAuto); begin // Hier nun die Daten holen und in AResult ablegen // Ein Create darf hier nicht mehr erfolgen! // AResult ist als const deklariert, damit man nicht versehentlich // eine weitere Instanz zuweist. end; Solange man das nicht selber auch so macht, und die Objektinstanzen einzeln erzeugt, sollte man keine Objekt als Ergebnis zurückgeben (wie weiter oben schon erwähnt). |
Re: Handling von Objekten (vom Typ TObject)
Du musst dir ein Object, wenn du es so deklarierst
Delphi-Quellcode:
so vorstellen:
var
MyObj: TMyObject; - Du hast erstmal ein Speicherbereich (Heap), auf dem die ganzen Eigenschaften (Felder) gespeichert werden - Außerdem hast du einen Zeiger auf diesen Bereich Am Anfang ist nur der Zeiger da, der halt irgendwo hin zeigt (NIL - Not In List). Dieser Zeiger wird am Anfang der Procedure erstellt und am Ende der Procedure wieder gelöscht. Um jetzt mit dem Objekt arbeiten zu können musst du dir erstmal dein Speicherbereich auf dem Heap reservieren und den Zeiger darauf setzen. Das erledigst du mit dem sogenannten Konstructor:
Delphi-Quellcode:
Das ist immer zwingend notwendig, wenn du auf einen Zeiger zugreifst der nirgendwohin zeigt gibts ne Zugriffsverletzung.
MyObj := TMyObject.Create;
Jetzt kannst du dir zB ein Object erstellen und mehrere Zeiger darauf haben:
Delphi-Quellcode:
Das .free nicht vergessen, da der reservierte Speicherbereich sonst im Heap bleibt und erst am Ende, wenn das Programm beendet wird, freigegeben wird (-> Speicherleck).
var
MyObj1, MyObj2: TMyObject; begin MyObj1 := TMyObject.Create; // Speicherplatz reservieren und Zeiger MyObj1 ausrichten MyObj2 := MyObj1; // Auch noch den 2ten Zeiger ausrichten MyObj2.Eigenschaft := 'Bla'; MyObj1.Eigenschaft := 'Hallo'; Showmessage(MyObj2.Eigenschaft); // Da wir auf den gleichen Speicherbereich zugreifen kommt "Hallo" MyObj2.Free; // Den reservierten Speicherplatz wieder freigeben TMyObject.Create; // auch das ist möglich, blöderweise haben wir dann kein zeiger darauf -.- end; Bei deiner oben genannten Funktion werden nur die Zeiger weitergegeben, da diese Zeiger schon auf einen Speicherbereich zeigen musst du in diesem Fall den Konstructor und Destructor (free) weglassen. Nochmal ganz konkret: Mit dem Konstructor reservierst du Speicher und setzt deinen Zeiger darauf, bei deiner Funktion ist der Speicher schon da und du veränderst nur den Zeiger. |
Re: Handling von Objekten (vom Typ TObject)
Jungs, ihr seid super! Dank euren Beispielen glaube ich den Großteil verstanden zu haben. Ich hoffe ich kann´s nun in meinem Programm richtig benutzen :-)
DANKE! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz