So, jetzt nochmal gaaaaaanz laaaaangsam, und schoooooeeen detailliert:
Regeln:
- Wird eine Methode als virtual deklariert, erhaelt sie einen Eintrag in der VMT.
- Wird eine Methode als override deklariert, wird der vorherige Eintrag der VMT ueberschrieben.
- Welche VMT verwendet wird, entscheidet das Instanzieren. Es wird immer auf die VMT verwiesen, dessen Konstruktor aufgerufen wurde.
So, und nun was passiert:
Gegeben sei folgende Klasse
Delphi-Quellcode:
TMeineKlasse = class(TObject)
constructor Create();
destructor Destroy(); //override;
end;
und diese 2 Variablen:
Delphi-Quellcode:
var
meineKlasseObject: TObject;
meineKlasse: TMeineKlasse;
welche beide mit
TMeineKlasse.Create();
initialisiert werden.
Beobachten wir nun beide moeglichkeiten, und rufen bei beiden Instanzen die Destroy-Methode auf (weil du ja meinst, mit Free waere das ganze gezinkt
)
Zuerst ohne override:
meineKlasse.Destroy();
Der Kompiler guckt: meineKlasse ist als TMeineKlasse deklariert. Davon soll nun die Methode "Destroy" aufgerufen werden. Ja, die is da deklariert, und dementsprechend wird auch TMeineKlasse.Destroy aufgerufen.
nun
meineKlasseObject.Destroy();
Der Kompiler guckt: meineKlasseObject ist als TObject deklariert. Davon soll nun die Methode "Destroy" aufgerufen werden. Ja, TObject.Destroy() gibts, und ist als virtual derklariert. Also guckt er in der
VMT nach: Durch das instanzieren mit TMeineKlasse.Create() wird auf die
VMT von TMeineKlasse verwiesen. Dort findet sich allerdings immernoch nur der Eintrag auf TObject.Destroy(), also wird TObject.Destroy aufgerufen. -> Speicherleck (siehe mein vorheriger Beitrag).
so, und nun das ganze mit override:
beim aufruf von
meineKlasse.Destroy
veraendert sich nichts. Der Kompiler sieht immernoch die Methode TMeineKlasse.Destroy() (weil meineKlasse als TMeineKlasse deklariert ist), und ruft dementsprechend auch TMeineKlasse.Destroy() auf.
Der Unterschied kommt bei
meineKlasseObject.Destroy();
Hier guckt naemlich der Kompiler: Es soll die Methode Destroy von TObject aufgerufen werden. Diese Methode ist als virtual deklariert. Also gucken wir in der
VMT nach. Weil diese aufgrund des Instanzierens durch TMeineKlasse.Create auf die
VMT von TMeineKlasse geleitet wird, und der Eintrag von Destroy durch das override auf TMeineKlasse.Destroy() ueberschrieben wird, ruft der Kompiler auch TMeineKlasse.Destroy() auf -> Kein Speicherleck.
[Edit]Absatz entfernt. Er kam etwas persoenlich angreifender rueber als erhofft. Sorry, Klaerung per PN erfolgt.[/Edit]
greetz
Mike