![]() |
Delphi-Version: 5
Problem mit Constructor/Destructor
hi leute,
bin neu hier im forum und hab gleich ein problem. nach stundenlangen herumprobieren weiss ich nicht mehr weiter :( habe erst seit kurzem angefangen mit klassen zu arbeiten.. und scheitere bereits beim constructor bzw. dem pointer darauf. Hier erstmal die Unit mit der Class:
Delphi-Quellcode:
und dann..
UNIT UContainer;
INTERFACE USES SysUtils; TYPE TContainer=Class Private FFileName:String; Procedure DoSomething; Public Constructor Create(const FileName:String;AsReadOnly:Boolean); Destructor Destroy;override; End; IMPLEMENTATION Constructor TContainer.Create(constFName:String;AsReadOnly:Boolean); Begin inherited Create; If FileExists(FName)Then Begin //HandleFile; //.. End Else Destroy End; Destructor TContainer.Destroy; Begin inherited Destroy End; END.
Delphi-Quellcode:
ich möchte also eine klasse erzeugen, die falls ein problem auftaucht (z.b. nicht existierende datei) sich gleich mittels destructor selbst zerstört. Durch aufruf des destructors sollte doch eigentlich auch der pointer darauf auf nil gesetzt werden? das passiert aber nicht! wie kann man sonst herausfinden ob die klasse noch existiert?
var
P:Pointer; Begin P:=TContainer.Create('C:\Non-Existing-File.txt',False); If P=NIL Then ShowMessage('P is NIL') Else ShowMessage('P is NOT NIL'); TContainer(P).DoSomething; //..erzeugt Exception! End; vielen dank! gruss markus |
AW: Problem mit Constructor/Destructor
Die von dir designte Klasse ist höchst "interessant". Ich würde es so lösen:
Delphi-Quellcode:
Dann kannst du im Create prüfen ob die Datei geöffnet werden kann und ansonsten setzt du FInvalidFile auf true. In keinen Fall darfst du im Constructor Destroy aufrufen. Das ist tödlich :D
type
TContainer = class(TObject) private FFileName: String; FInvalidFile: Boolean; public procedure DoSomeThing; constructor Create(const FileName: String; AsReadOnly: Boolean); destructor Destroy; published property InvalidFile: Boolean read FInvalidFile; end; |
AW: Problem mit Constructor/Destructor
Destroy sollte generell nicht aufgerufen werden, sondern Free.
Im Constructor allerdings auch kein Free ;) Das Zerstören einer Instanz setzt die Referenzen nicht auf nil. Darum muss man sich selber kümmern (gibt da ein ![]() |
AW: Problem mit Constructor/Destructor
Auch keine gute Lösung. Denn man bekommt erstmal nichts von dem Fehler mit.
Der "best practise" Weg ist eine Exception im Konstruktor zu werfen. Wenn das passiert, wird das Objekt automatisch wieder aufgeräumt und der Ersteller bekommt eine deutliche Warnung ;) |
AW: Problem mit Constructor/Destructor
Da kann man sicherlich geteilter Meinung sein. Ich persönlich mag Klassen, die in ihren Methoden Exceptions werfen absolut nicht. Ich meine normalerweise würde man folgendes machen:
Delphi-Quellcode:
Einen spezifischen Fehlercode kann man zur not auch noch irgendwo hinterlegen.
var
Container: TContainer; begin Containter := TContainer.Create(FileName); try if not Container.InvalidFile then begin end; finally Container.Free; end; end; |
AW: Problem mit Constructor/Destructor
wow, vielen dank für die schnellen antworten! habe schon befürchtet, dass man im constructor nicht gleich wieder den destructor aufrufen darf.. wäre auch zu schön gewesen! werde wohl den code auf mehrere blöcke aufteilen müssen, ähnlich Zacherl es vorgeschlagen hat. ein problem bleibt dennoch: wie kann ich herausfinden ob eine klasse noch existiert? sir rufo sagte bereits, dass das Zerstören die Referenzen nicht auf nil setzt! somit dürfte ja folgendes beispiel NICHT funktionieren..
Delphi-Quellcode:
..aber wie kann ich dann mittels eines Pointers der auf eine Klasse verweist herausfinden ob diese überhaupt noch existiert (ohne eine exception aufzurufen)? naja werde mich wohl oder übel eingehender mit pointer, klassen etc. beschäftigen müssen ;) danke für eure geduld
var
pFolder:Array Of ^TFolder; Procedure RemoveFolder(Index:Integer;Recurse:Boolean); Begin //TFolder(pFolder[Index]).DeleteChilds... TFolder(pFolder[Index]).Destroy; End; und dann später.. Procedure UpdateListItems; var i:Integer; Begin For i:=0To Pred(Length(pFolder))Do If TFolder(pFolder[i])=NIL Then RemoveListItem End; |
AW: Problem mit Constructor/Destructor
Du könntest aber auch eine
Delphi-Quellcode:
bemühen, die dir ein entsprechendes Objekt zurückliefest oder eben nicht (nil)
class function
|
AW: Problem mit Constructor/Destructor
Dann halt statt
Delphi-Quellcode:
finally
Container.Free; end;
Delphi-Quellcode:
Btw nie Destroy direkt aufrufen
finally
FreeAndNil( Container); end; Zudem würde ich statt eines arrays eine Liste verwenden |
AW: Problem mit Constructor/Destructor
Zitat:
Zuerst zu dem Fehlercode: Das läuft auf das Gleiche hinaus wie die Property. Man kann sie ignorieren. Und das ist nicht gut. Unter anderem aus diesem Grund gibt es ja gerade die Exceptions, damit nicht jede Klasse ihren eigenen Fehlermechanismus implementieren muss. Das zweite: Man lässt den Code einfach mal laufen und guckt dann nachher, ob es einen Fehler gegeben hat. Warum nicht vorher prüfen?
Delphi-Quellcode:
Falls die Prüfung vorher tatsächlich nicht gewünscht ist, geht immer noch das hier:
var
Container: TContainer; begin if Fileexists(FileName) then begin Containter := TContainer.Create(FileName); try //Was machen finally Container.Free; end; end; end;
Delphi-Quellcode:
Wenn der Konstruktor eine Exception wirft, wird die Variable nicht verändert - bleibt also nil.
try
Containter := TContainer.Create(FileName); except end; If Containter=NIL Then ShowMessage('Containter is NIL') Else ShowMessage('Containter is NOT NIL'); Containter.DoSomething; //..erzeugt Exception! Der Zugriff am Ende erzeugt aber immer noch eine AV. |
AW: Problem mit Constructor/Destructor
es funzt! keine ahnung ob des professionell gelöst ist, aber es geht erstmal
Delphi-Quellcode:
UNIT UContainer;
INTERFACE USES SysUtils; VAR pSelf:Pointer; TYPE TContainer=Class Private FFileName:String; //pLevel:Arary Of ^TLevel; //Procedure HandleFile; //.. Public Class Function Alive:Boolean; Constructor Create; Destructor Destroy;override; Procedure Assign(const FName:String;AsReadOnly:Boolean); Property FileName:String Read FFileName; //.. End; IMPLEMENTATION Class Function TContainer.Alive:Boolean; Begin Result:=pSelf<>NIL End; Constructor TContainer.Create; Begin inherited Create; pSelf:=Pointer(Self); //.. End; Destructor TContainer.Destroy; Begin //.. pSelf:=NIL; inherited Destroy End; Procedure TContainer.Assign(const FName:String;AsReadOnly:Boolean); Begin If Not FileExists(FName)Then Begin //Destroy Free End End; END.
Delphi-Quellcode:
Danke an alle! ;) und gute n8
var
P:Pointer; Begin P:=TContainer.Create; TContainer(P).Assign('C:\Non-Existing-File.txt',False); If NOT TContainer(P).Alive Then Begin ShowMessage('Klasse existiert nicht mehr!'); P:=NIL End End; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:48 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