AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Methodenhierarchie in der Vererbung umgehen/überspringen
Thema durchsuchen
Ansicht
Themen-Optionen

Methodenhierarchie in der Vererbung umgehen/überspringen

Ein Thema von scouty · begonnen am 10. Jan 2004 · letzter Beitrag vom 13. Jan 2004
 
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#8

Re: Methodenhierarchie in der Vererbung umgehen/überspringen

  Alt 12. Jan 2004, 14:56
@Choose: die .CommonMethod() in meinem Beispiel zeigt wie es OOP konform zu lösen ist.

@scouty: Es sind virtuelle/Dynamische Methoden und exakt weil deine TypCast Methode nicht funktionieren kann, habe ich dir die beiden Wege aufgezeigt.

Nun, warum kann ein TypCast nicht funktionieren ?
Jedes allozierte Object hat intern einen Zeiger auf seine Klasse. Eine Klasse ist nichts anderes als eine Speicherstruktur die im Codesegement gespeichert wurde. D.h. werden zB. 100 Objecte vom Typ TMyObject erzeugt so zeigen alle diese 100 Objecte auf ein und dieselbe Klassendefinition ins Codesegement. In dieser Klassendefinition sind zB. der ClassName, ParentClass, ClassType, die VMT = Virtual Method Table, die DMT = Dynamic Method Table usw. usw. gespeichert. Wird nun eine Virtuelle Methode aufgerufen so wird aus der Klassendefinition in der VMT die realle Addresse der Methode die aufgerufen werden soll ausgelesen. Der Code verzeigt nach diesem Auslesen also an diese Methodenadresse. Nun da Self.Classtype = TC ist wird somit immer auf die VMT von TC zugegriffen. In dieser VMT steht ein Zeiger auf @TC.Method und nicht TA.Method. Somit wird auch bei einem TypCast trotzdem TC.Method aufgerufen. So und nicht anders SOLLEN virtuelle methoden auch funktionieren.

Um aber wiederum zu tricken, müssen wir also den Klassentyp von Self= TC in den Klassentyp TA ändern. Nachdem dies passiert ist würde man mit TC(Self).Method() nun tatsächlich TA.Method aufrufen. Dies geht dann so:

Delphi-Quellcode:
procedure TC.Method(Dummy: Integer);
type
  PPointer = ^Pointer;
var
  N: procedure(Dummy: Integer) of object;
begin
  inherited;
  ShowMessage('TC');

// nun rufen wir inherited TA.Method(Dummy) auf
  TMethod(N).Data := Self;
  TMethod(N).Code := @TA.Method;

  N(Dummy);

// nun so wie es auf herkömmliche OOP Weise funktioniert
  CommonMethod(Dummy);

// hier wird die Klasse TC von Self^ in Klasse TA gepatcht, und wieder zurück
  ShowMessage('Klassenname ist ' + ClassName);
  PPointer(Self)^ := TA;
  ShowMessage('Klassenname ist ' + ClassName);
  Method(Dummy);
  PPointer(Self)^ := TC;
end;
Im letzten Code siehtst du also das der erste Zeiger im Speicher von Self^ ein Zeiger auf den Klassentyp von Self ist. Jedes Object speichert also als erstes unsichtbares Feld seinen eigenen Klassentyp. Der Klassentyp selber ist nichts anderes als ein Zeiger in das Codesegment wo der Compiler die Klassendefinition abgelegt hat. Biegen wir diesen Zeiger um so können wir den Klasentyp eines beliebigen Objectes auf einen anderen Klassentyp patchen. Aber Vorsicht dies hat gravierende Konsequenzen.
In unserem Fall hat dies zu Konsequenz das nun die VMT=Virtuelle Methoden Tabelle von Self nicht mehr die originale von TC ist sondern die von TA. Somit wird der nachfolgende Aufruf von Self.Method() nicht wie erwartet eine Rekursion hervorufen, sondern eben TA.Method() aufrufen.

Gruß Hagen
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:04 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