Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wann ein "inherited" im Constructor ? (https://www.delphipraxis.net/82508-wann-ein-inherited-im-constructor.html)

Muetze1 14. Dez 2006 21:21

Re: Wann ein "inherited" im Constructor ?
 
Ok, ich hatte nämlich im Code nachgeschaut und da TPen und TBrush mit ihren nicht virtuellen Constructoren auch kein inherited aufruft, dachte ich, du meinst dies als Bestätigung meiner These. In der VCL von Delphi 5 ist der Kommentar im Constructor von TGraphic nicht vorhanden, daher kam auch die Frage.

Ok, nun habe ich Bezug auf die Feststellungen hier noch ein Frage: Diese Constructor-Definitionen die wir hier nun haben (nicht virtuell, etc) - was für eine Art von Handling ist dies nun? Werden die Constructoren automatisch versteckt (bei anderer Signatur) und der neue eingeführt bzw. bei gleicher Signatur überschrieben?

Beispiel dazu wie ich es meine:
Delphi-Quellcode:
type
  TTest1 = Class
  Public
    Constructor Create;
  End;

  TTest2 = Class(TTest1)
  Public
    Constructor Create(Param: Integer);
  End;

  TTest3 = Class(TTest2)
  Public
    Constructor Create(neuerparam: Double);
  End;
TTest3.Create bietet mir Code-Insight nur den Constructor von TTest3 an.

/EDIT: richtig virtuell können sie ja nicht sein - somit: wie wird das gehandhabt?

Robert Marquardt 15. Dez 2006 05:10

Re: Wann ein "inherited" im Constructor ?
 
Man sollte immer inherited aufrufen. Auch fuer von TObject direkt abgeleitete Klassen. Da gibt es kein Problem und man kann spaeter enoetigenfalls eine Klassenstufe dazwischenschieben und hat dann keine Probleme mit einem vergessenen inherited-aufruf. So machen wir es in der JVCL und es hat bis heute gut geklappt.

Muetze1 15. Dez 2006 19:24

Re: Wann ein "inherited" im Constructor ?
 
Zitat:

Zitat von Robert Marquardt
Man sollte immer inherited aufrufen. Auch fuer von TObject direkt abgeleitete Klassen. Da gibt es kein Problem und man kann spaeter enoetigenfalls eine Klassenstufe dazwischenschieben und hat dann keine Probleme mit einem vergessenen inherited-aufruf. So machen wir es in der JVCL und es hat bis heute gut geklappt.

Ja, ok - hatten wir ja nun geklärt das dies eh immer nötig ist. Nun würde ich aber gerne noch meine Frage beantwortet haben...

jbg 15. Dez 2006 22:24

Re: Wann ein "inherited" im Constructor ?
 
Virtuelle Konstruktoren sind virtuelle Methoden der Metaklasse. Die Konstruktor-Virtualität wird nur für Klassenreferenzen (Variablen vom Typ der Metaklasse: class of TMyClass) benötigt. Es ist daher für die direkte Instanzierung einer Klasse unerheblich, ob der Konstruktor nun virtuell ist oder nicht, da man ihn direkt aufruft und nicht über die VMT der Metaklasse geht.

Beim Aufruf eines Konstruktor übergibt der Compiler einen versteckten Parameter (im DL-Register), der angibt, ob der "begin"-Code des Konstruktors die NewInstance() Klassenmethode (Methode der Metaklasse) aufrufen soll, die ihrerseits Speicher reserviert. Ruft man nun mittels inherited den Vorfahrkonstruktor auf, enthält dieser versteckte Parameter einen anderen Wert, wodurch kein erneutes NewInstance durchgeführt wird. Das inherited führt also den Vorfahrkonstruktor als normale Methode aus.

Und wann sollte man inherited aufrufen? Immer dann wenn man die Funktionalität der Vorfahrklasse benötigt. Dies trifft beim Konstruktor natürlich immer dann ein, wenn der Vorfahrkonstruktor eine Initialisierung des Objekts vornimmt und man nicht aus irgendwelchen Gründen dies unterbinden will. Da TObject.Create nicht wirklich viel macht, außer dem "begin"-Code, der aber auch im Konstruktor der abgeleiteten Klasse vorhanden ist, ist es nicht unbedingt notwendig TObject.Create mittels inherited aufzurufen, da dort nichts mehr passiert. Stellt man aber zu einem späteren Zeitpunkt fest, dass man vielleicht doch besser eine Klasse dazwischen schieben sollte, kann das fehlende [b9inherited[/b] einem sehr viel Kopfschmerzen bereiten.

Das inherited ist übrigens nicht mit dem virtual verbunden. Ein inherited wird vom Compiler immer direkt in einen absoluten Methoden-Aufruf ohne Umweg über die VMT kompiliert. Es findet also keine Bindung zur Laufzeit statt, sondern bereits zur Link-Zeit.


Wenn Borland/CodeGear immernoch die Handbücher zu TurboPascal 4.0, 5.0 und 5.5 verkaufen würde, wüssten einige Programmierer mehr über manche Interna bescheid. Aber leider wurden die Handbücher (so fern sie noch ausgeliefert wurden) immer schlechter. Und wer kämpft sich schon durch die CPU-View beim Debuggen durch?

jbg 15. Dez 2006 22:31

Re: Wann ein "inherited" im Constructor ?
 
Zitat:

Werden die Constructoren automatisch versteckt (bei anderer Signatur) und der neue eingeführt bzw. bei gleicher Signatur überschrieben?
Konstruktoren werden hier nicht anders behandelt als normale Methoden. Ohne ein overload wird der geerbte versteckt.

Robert Marquardt 16. Dez 2006 04:47

Re: Wann ein "inherited" im Constructor ?
 
Das ist nicht so ganz einfach mit dem Verstecken der Konstruktoren. Siehe meinen TJvHidDeviceController.
Ein privater Konstruktor verbirgt eben nicht den von TObject geerbten Konstruktor.
Ich habe deshalb den Konstruktor ueberschrieben und mittels Exception unbrauchbar gemacht und einen anders benannten privaten Konstruktor eingefuehrt.

Muetze1 16. Dez 2006 11:37

Re: Wann ein "inherited" im Constructor ?
 
Zitat:

Zitat von Robert Marquardt
Ein privater Konstruktor verbirgt eben nicht den von TObject geerbten Konstruktor.

Du änderst ja auch die Sichtbarkeit, das stand hier nicht zur Debatte. Ich bezog mich bei meiner Frage rein auf das Handling bei gleichbleibender Sichtbarkeitsebene.

Du kannst beim Überschreiben keine Methode in eine geringere Sichtbarkeit überführen.

Zitat:

Zitat von jbg
Zitat:

Werden die Constructoren automatisch versteckt (bei anderer Signatur) und der neue eingeführt bzw. bei gleicher Signatur überschrieben?
Konstruktoren werden hier nicht anders behandelt als normale Methoden. Ohne ein overload wird der geerbte versteckt.

Stimmt, nur bei virtuellen meckert er die verdeckte Methode an. Ich hatte da mal wieder das Compilerverhalten von virtuellen Methoden auf diese nicht-virtuelle Form angewandt - mein Fehler.

Zitat:

Zitat von jbg
Wenn Borland/CodeGear immernoch die Handbücher zu TurboPascal 4.0, 5.0 und 5.5 verkaufen würde, wüssten einige Programmierer mehr über manche Interna bescheid. Aber leider wurden die Handbücher (so fern sie noch ausgeliefert wurden) immer schlechter. Und wer kämpft sich schon durch die CPU-View beim Debuggen durch?

Guter Tipp, danke! Ich habe die Handbücher hier komplett rumliegen, aber ich dachte bisher, dass die alte OBJECT Lösung von Pascal nicht mehr zeitgemäß ist bzw. das neue System mit Delphi auch ein anderes Verhalten mitgebracht hat. Ich werde mir die Bücher mal zu Gemüte führen.

Vielen Dank an jbg und allen anderen für die Erklärungen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:21 Uhr.
Seite 2 von 2     12   

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