Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Warum virtuelle Destructoren? (https://www.delphipraxis.net/86842-warum-virtuelle-destructoren.html)

Muetze1 19. Feb 2007 09:12

Re: unsichtbare Klassen
 
gleiches gilt neben dem Aufruf von xxx.Free; auch für die Verwendung/Aufruf von FreeAndNil(xxx);

Hansa 19. Feb 2007 18:42

Re: unsichtbare Klassen
 
Vorab : der Thread hier wurde vom Fragesteller woanders mittlerweile als OT gebrandmarkt. :mrgreen:

Nichtsdestotrotz : das ganze sieht doch so aus :

Delphi-Quellcode:
destructor TObject.Destroy;
begin
end;
Wie Muetze richtig aus der Hilfe zitiert hat, ist es dasselbe einfach "class" zu schreiben oder eben "class (TObject)". Also ist das ein Nachfahre von TObject. Aber nur pro forma. Warum soll jetzt da nochmals ein leerer Destructor per override auch noch überschrieben werden ? :shock: Vermute sogar, dass der Delphi-Linker das automatisch entfernt. Naheliegend wäre auch, das die vereinfachte Schreibweise Class erlaubt wird, damit keiner auf die Idee kommt, so was überflüssigerweise zu machen. :-D

JasonDX 19. Feb 2007 19:09

Re: unsichtbare Klassen
 
Zitat:

Zitat von Hansa
Also ist das ein Nachfahre von TObject. [...] Warum soll jetzt da nochmals ein leerer Destructor per override auch noch überschrieben werden ? :shock:

Hmm, ein paar OOP-Tutorials wuerden dir nicht schlecht tun:
Du hast eine beliebige Klasse, bspw. TMeineKlasse. Im Konstruktor dieser Klasse wird bspw. Speicher allociert, oder irgendetwas instanziert, das im Destruktor wieder freigegeben werden muss.
Nun gibts 2 Moeglichkeiten:
Delphi-Quellcode:
//1.
destructor Destroy();
//2.
destructor Destroy(); override;
Du behauptest, zweiteres mache keinen Sinn. Analysieren wir mal, was die unterschiede sind:
Wenn eine Variable als TMeineKlasse deklariert ist, macht es keinen Unterschied.
Wenn aber eine Variable nicht als TMeineKlasse, sondern als Vorfahre (bspw. TObject) deklariert ist, aber als TMeineKlasse instanziert wurde, muss auch der Destruktor von TMeineKlasse aufgerufen werden.
Passiert das aber? Nein.
Delphi-Quellcode:
TMeineKlasse = class
  constructor Create();
  destructor Destroy();
  speicher: Pointer;
end;
//...
constructor TMeineKlasse.Create();
begin
  speicher = allocmem(100);
end;

destructor TMeineKlasse.Create();
begin
  freemem(speicher);
end;



procedure ProbiersAus();
var
  x: TObject;
begin
  x := TMeineKlasse.Create();
  x.Free(); //Es wird TObject.Free aufgerufen!
end;
Gibt ein schoenes Speicherleck. mit dem ueberschreiben des Destruktors passiert das nicht.

greetz
Mike

Muetze1 19. Feb 2007 19:10

Re: unsichtbare Klassen
 
Zitat:

Zitat von Hansa
Warum soll jetzt da nochmals ein leerer Destructor per override auch noch überschrieben werden ?

Weil sonst sein FObject.Free bzw. das Clear nicht aufgerufen wird in seinem Constructor. Das Override ist notwendig, sonst wird der Destructor in der Ableitung nicht aufgerufen (siehe vorherige Ausführungen). Der Destructor in TObject ist leer, ok, aber dann könntest du vllt. propagandieren, dass der Inherited Aufruf weggelassen werden könnte - das stimmt, aber das Override ist notwendig für den Aufruf.

Den Aufruf von Inherited würde ich aber auch nicht weglassen, da sonst bei einer Änderung des Inhalts des Destructors in TObject seitens Borlands nicht Rechnung getragen würde.

/EDIT: roter Rahmen verzweifelt gesucht...

IngoD7 19. Feb 2007 20:13

Re: unsichtbare Klassen
 
Zitat:

Zitat von Hansa
Warum soll jetzt da nochmals ein leerer Destructor per override auch noch überschrieben werden ? :shock:

Deshalb:

Zitat:

Zitat von IngoD7
Zitat:

Zitat von Muetze1
/EDIT: Wenn du das Override nicht angibst, dann erhälst du zum einen einen Hinweis/Warnung vom Compiler und zum anderen wird dein Destructor nie ausgeführt.

Das bedarf aber noch ein paar Erklärungen. ;-)

Er wird [...] nicht ausgeführt, wenn zum Freigeben von TMeinObjekt ein MeinObjekt.Free benutzt wird. Free ist von TObject geerbt und ruft eben nur den Destruktor destroy von TObject auf, wenn dessen Virtualität nicht Rechnung getragen wird in den abgeleiteten Klassen. Durch ein override würde MeinObjekt.Free den Destructor destroy von TMeinObjekt aufrufen. Daher sollten Destruktoren in der Regel immer ihren Ahnen per override überschreiben. Eben weil sonst ein Free den eigenen Destruktor nicht "erreichen" würde, sondern in TObject "hängenbleiben" würde.
[...]

Probiere es aus. :)

IngoD7 19. Feb 2007 20:26

Re: unsichtbare Klassen
 
@JasonDX

Zitat:

Zitat von JasonDX
Wenn eine Variable als TMeineKlasse deklariert ist, macht es keinen Unterschied.

Doch. Bei Benutzung von Free macht es immer einen Unterschied. Es gibt in der Regel nur das eine, geerbte Free in TObject. Das wird auch angesprungen wenn ein TMeineKlasse.Free aufgerufen wird. Und dieses angesprungenen TObject.Free würde jetzt nur den eigenen Destructor (in TObject) aufrufen, wenn der Destructor der abgeleiteten Klasse TMeineKlasse kein override besitzt. Und das eben auch bei
Delphi-Quellcode:
var
  x: TMeineKlasse;
Dieser "Umweg" über das Free, welches nur im Urahnen TObject existiert, macht beim Aufruf des Destructors den kleinen Unterschied.

Hansa 19. Feb 2007 20:34

Re: unsichtbare Klassen
 
Ich liebe Grundsatzdiskussionen, aber wir sind anscheinend noch lange nicht fertig. :mrgreen:

Erkläre mir mal bitte einer, was ich in diesem Fall mit dem overrride soll :
Delphi-Quellcode:
Unit Unit2;

interface

implementation

uses
  Dialogs,
  SysUtils;

type

TMeineKlasse = class
  private
    i : integer;
  protected
    constructor Create;
    destructor Destroy;
end;

var MeineKlasse : TMeineKlasse;

constructor TMeineKlasse.Create;
begin
  i := 123;
end;

destructor TMeineKlasse.Destroy;
begin
showmessage ('Destroy '+IntToStr (i));
end;

begin
  MeineKlasse := TMeineKlasse.Create;
showmessage (IntToStr (MeineKlasse.i));
  MeineKlasse.Destroy;
end.
Das Programm zeigt 2-mal '123' an, wie erwartet. Geht man dann noch hin und macht das IMHO überflüssige Destroy und alles was damit zusammenhängt weg, dann tut es das auch.

Wer hat ein Gegenbeispiel ? Es darf aber wirklich nur als Class deklariert sein. Das TObject-Free von Jason ist auch gemogelt, es geht um Destroy. Free hat eingebaute Funktionalität. Das ist schon was anderes.

IngoD7 19. Feb 2007 20:51

Re: unsichtbare Klassen
 
Moin Hansa,

das ist ungefähr das, was JasonDX meinte. Der direkte Aufruf von Destroy in deinem Beispiel verhält sich so, wie du sagst. Was anderes hatte JasonDX auch nicht behauptet.

Jetzt gibt es aber Fälle, wo (jetzt bezogen auf dein Beispiel) nicht
Delphi-Quellcode:
var MeineKlasse : TMeineKlasse;
sondern
Delphi-Quellcode:
var MeineKlasse : TObject;
gesetzt wird, und dennoch wie folgt created wird:
Delphi-Quellcode:
MeineKlasse := TMeineKlasse.Create;
Jetzt erreicht dein Code den Destructor von TMeineKlasse nicht mehr.

Zitat:

Zitat von Hansa
Das TObject-Free von Jason ist auch gemogelt, es geht um Destroy. Free hat eingebaute Funktionalität. Das ist schon was anderes.

Aber genau das ist gemeint!
Wer ruft denn bitteschön Destroy direkt auf? Für dein Beispiel war es jetzt ja ganz gut und schön und anschaulich. Aber in der Praxis sollte und wird die Methode Free oder die Procedure FreeAndNil() benutzt. Und genau dann ist override in jedem Fall erforderlich.

Hansa 19. Feb 2007 22:34

Re: unsichtbare Klassen
 
Zitat:

Zitat von IngoD7
das ist ungefähr das, was JasonDX meinte. Der direkte Aufruf von Destroy in deinem Beispiel verhält sich so, wie du sagst. Was anderes hatte JasonDX auch nicht behauptet.
...

Gut, dann schmeiße ich das eigene Destroy mal selber raus. Da ist nicht mehr viel zu entfernen.

Delphi-Quellcode:
Unit Unit2;

interface

implementation

uses
  Dialogs,
  SysUtils;

type

TMeineKlasse = class
  private
    i : integer;
    constructor Create;
end;

var MeineKlasse : TMeineKlasse;

constructor TMeineKlasse.Create;
begin
  i := 123;
end;

begin
  MeineKlasse := TMeineKlasse.Create;
showmessage (IntToStr (MeineKlasse.i));
end.
Kein Destroy mehr, auch kein override und es geht immer noch. Ich will lediglich wissen, was einige hier vorhaben mit override etc. Und sieh mal einer an, was steht denn da :

Delphi-Quellcode:
constructor TObject.Create;
begin
end;
:shock: Da ist ja sogar das Create eventuell fällig. :mrgreen:

Edit : es sei angemerkt, dass nicht mal inherited verwendet wird ! Normalerweise wäre das schon nötig.

IngoD7 19. Feb 2007 22:53

Re: unsichtbare Klassen
 
Zitat:

Zitat von Hansa
Zitat:

Zitat von IngoD7
das ist ungefähr das, was JasonDX meinte. Der direkte Aufruf von Destroy in deinem Beispiel verhält sich so, wie du sagst. Was anderes hatte JasonDX auch nicht behauptet.
...

Gut, dann schmeiße ich das eigene Destroy mal selber raus. Da ist nicht mehr viel zu entfernen.

Darum geht es doch gar nicht.

Du willst wissen, wie es sich mit virtuellen Methoden und override verhält? Fein. Steht hier in diesem Thread jetzt doppelt und dreifach. Lies in. ;-) In der Hilfe steht das ebenfalls recht ansprechend beschrieben. Die Geschichte mit Free ist zudem ein sehr schönes Beispiel für die Implemetierung in einer Klassenhierarchie. Kann man herrlich ausprobieren und (auch wenn's schwer ist) verstehen. Tue es, oder lass es. Ich habe keinen Bock, dir zu erklären, dass das Gras grün ist.

Wenn du jede Klasse ausschließlich so instantiierst wie sie deklariert ist und wenn du eigenen Klassen immer einen statischen Destruktor verpasst und diesen immer direkt mit xxx.Destroy aufrufst, dann wirst du möglicherweise immer zurecht kommen.

Oder um auf das Gras zurückzukommen: Wenn du dein ganzen Grundstück zupflasterst, ist das in Ordnung. Die Rasenflächen der Anderen sind aber immer noch grün - ganz egal, ob du das akzeptierst oder nicht. :spin2:


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:30 Uhr.
Seite 3 von 4     123 4      

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