Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Wer ruft destroy auf? (https://www.delphipraxis.net/178815-wer-ruft-destroy-auf.html)

iphi 29. Jan 2014 09:53

Wer ruft destroy auf?
 
Hallo,

hier ein kleines Codebeispiel zu meinem Problem, welches bei Programmstart ein Objekt dynamisch erzeugt und bei Programmende wieder verschwinden lässt:

Hauptunit:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit2;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    Test: TTest;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Test:=TTest.create(self);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Test.Free;
end;

end.
Unit2:
Delphi-Quellcode:
unit Unit2;

interface

uses classes, Windows;

type
  TTest = class(TComponent)
  private
  public
    constructor
              create(AOwner : TComponent); overload;
    destructor
              destroy; overload;
  published
  end;

implementation

constructor TTest.Create(AOwner : TComponent);
begin
  writeln('creating');
  inherited create(AOwner);
end;

destructor TTest.Destroy;
begin
  inherited destroy;
  writeln('destroyed');
  sleep(1000);
end;

end.
Mein Destructor TTest.Destroy wird nie aufgerufen. Warum? Ich dachte, Test.Free bewirkt, dass der Destruktor von TTest aufgerufen wird.

Sir Rufo 29. Jan 2014 09:55

AW: Wer ruft destroy auf?
 
Statt
Delphi-Quellcode:
overload
musst du
Delphi-Quellcode:
override
nehmen!

Das kann einem nicht passieren, wenn man das CodeCompletion benutzt.
Innerhalb der Klassendefinition Strg-Leer drücken (oder war es Shift-Strg-Leer) und du bekommst alle virtuellen Methoden/Properties der Vorgänger-Klasse angezeigt und kannst die gewünschte mit Enter übernehmen.
(Mehrfachauswahl geht übrigens auch)

Die IDE komplettiert jetzt die Klasse und sortiert alles auch in die richtigen Bereiche (protected/public/published) ein.

Der schöne Günther 29. Jan 2014 09:56

AW: Wer ruft destroy auf?
 
Außerdem würde ich den geerbten Destruktor doch am Ende deines Destruktor mittels
Delphi-Quellcode:
inherited
aufrufen, nicht am Anfang?

PS: Tolles Minimalbeispiel! Man sieht direkt um was es geht und muss nicht lange herumraten.

himitsu 29. Jan 2014 09:58

AW: Wer ruft destroy auf?
 
Bei TForm1 stimmt aber was nicht.

OnClose ist nicht das Gegenstück von OnCreate ... das ist nämlich OnDestroy.
Wenn man die Form mehrfach anzeigt und zwischendurch nur "ausblendet", dann wird nur einmal OnCreate, aber mehrmals Onclose ausgrufen, womit es beim zweiten Durchgang hoffentlich schön knallen wird.


PS: Dein TTest ist doch ein TComponent und du setzt den Owner auf die Form ... der Owner kümmert sich um die Freigabe und wenn die TForm1 freigegeben wird, würde es dann auch automatisch das TTest mit freigeben. (wenn du es nicht vorher "unnötiger" Weise, schon freigegeben hast)

jaenicke 29. Jan 2014 10:00

AW: Wer ruft destroy auf?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1245819)
Außerdem würde ich den geerbten Destruktor doch am Ende deines Destruktor mittels
Delphi-Quellcode:
inherited
aufrufen, nicht am Anfang?

Solange du auf keine Eigenschaften der Elternklasse zugreifst, ist das ja egal. Wichtig ist es nur, wenn du z.B. auf ein Objekt einer Elternklasse zugreifst, das im Destruktor dann natürlich zerstört wird, wenn du ihn vor deinem Code aufrufst.

Insofern macht es Sinn den geerbten Destruktor immer nach dem eigenen Code aufzurufen um da keinen Fehler zu machen, aber ein allgemeines Muss ist es nicht. Die Zerstörung des Objekts an sich passiert erst nach dem eigenen Destruktor.

Nebenbei noch als Erklärung:
overload fügt eine weitere Methode mit dem selben Namen hinzu, die dann andere Parameter haben kann als andere in der selben Klasse, override hingegen überschreibt die ursprüngliche Methode, so dass deine statt dieser aufgerufen wird.

iphi 29. Jan 2014 10:02

AW: Wer ruft destroy auf?
 
Zitat:

Statt overload musst du override nehmen!
Uff, danke! Manchmal sieht man den Wald vor lauter Bäumen nicht...

Und danke für die vielen Tipps!

himitsu 29. Jan 2014 10:06

AW: Wer ruft destroy auf?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1245819)
Außerdem würde ich den geerbten Destruktor doch am Ende deines Destruktor mittels
Delphi-Quellcode:
inherited
aufrufen, nicht am Anfang?

Das kommt drauf an, wes man erreichen will.
Soll der Code vor den Freigaben der Elternklassen sein, oder danach.
Aber im Allgemeinen macht es sich gut, wenn das inerited im Create am Anfang und beim Destroy am Ende steht, da man im Code ja oftmals funktionen nutzen will, welche da schon/noch vom Vorfahren vorhanden sein sollten.


Man kann es auch mitten drin aufrufen.
Delphi-Quellcode:
WriteLn('destroying');
...
inherited;
...
WriteLn('destroyed');
Eventuell kann man auch AfterConstruction und BeforeDestruction verwenden.

Sir Rufo 29. Jan 2014 10:14

AW: Wer ruft destroy auf?
 
Liste der Anhänge anzeigen (Anzahl: 4)
Hier mal eine kleine Foto-Story zum CodeCompletion

Innerhalb der Klassendefinition Strg-Leer drücken
Anhang 40627
Jetzt die Anfangsbuchstaben der gewünschten Methode eintippen (für Create einfach mal cr)
Anhang 40628
Die Auswahl mit Enter bestätigen und ...
Anhang 40629
Und jetzt noch mal Shift-Strg-C und wir können loslegen
Anhang 40630
Einfacher geht es nicht mehr :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz