Delphi-PRAXiS

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)

EccoBravo 14. Dez 2006 16:40


Wann ein "inherited" im Constructor ?
 
Hallo,

wann muß ich ein inherited im Constructor verwenden?

Vielen Dank

E. B.

Dax 14. Dez 2006 16:43

Re: Wann ein "inherited" im Constructor ?
 
Ganz klar: immer.

Wenn du es lääst, wird der Konstruktorcode der Parentklasse nicht ausgeführt: viele Felder, die man später hundertprozentig braucht, bleiben uninitialisiert.

SirThornberry 14. Dez 2006 16:45

Re: Wann ein "inherited" im Constructor ?
 
immer dann wenn du den Constructor der Klasse ausführen willst.
Bei TObject macht es nicht viel Sinn da der Constructor leer ist.
Bei TComponente ist es hingegen wieder vorraussetzung um ordentlich damit arbeiten zu können weil recht viel im Constructor initialisiert wird was auch von Nachfahren benötigt wird.
Man kann eigentlich immer mit inherited den Constructor der Klasse aufrufen von der man erbt außer man will nicht dass das ausgeführt wird.

Muetze1 14. Dez 2006 17:47

Re: Wann ein "inherited" im Constructor ?
 
Frage an die bisherigen Antworter (juhu, ein neues Wort erfunden...): Warum nicht einfach sagen, immer wenn der Constructor virtuell ist in der Basisklasse und wir ihn überschrieben haben (bzw. neu implementieren und den alten verstecken)? Afair ist ohne einen virtuellen Constructor auch kein Zwang da, inherited auf zu rufen.

Dies ist meine Behauptung, und nun ihr... :zwinker:

SirThornberry 14. Dez 2006 17:52

Re: Wann ein "inherited" im Constructor ?
 
auch ein virtueller Constructor muss nicht zwangsläufig nach dem Überschreiben aufgerufen werden wenn im Constructor nix drin steht und dieser nur dazu dient das abgeleitete Klassen bestimmte Parameter erwarten.

Muetze1 14. Dez 2006 18:00

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

Zitat von SirThornberry
auch ein virtueller Constructor muss nicht zwangsläufig nach dem Überschreiben aufgerufen werden wenn im Constructor nix drin steht und dieser nur dazu dient das abgeleitete Klassen bestimmte Parameter erwarten.

Ok, das war mir auch klar und darauf bezog ich mich nicht. Ich meinte den anderen Fall: Constructor nicht virtuell (z.B. von einer Ableitung von einer Ableitung von TObject).

Hawkeye219 14. Dez 2006 18:07

Re: Wann ein "inherited" im Constructor ?
 
Thomas, schau dir mal den Constructor von TPen oder TBrush an...

Gruß Hawkeye

Muetze1 14. Dez 2006 18:21

Re: Wann ein "inherited" im Constructor ?
 
Ja, ok, somit hatte ich Recht mit meiner Annahme bzw. Frage. Das inherited muss aufgerufen werden, wenn der Constructor in der Basisklasse virtuell ist und er somit überschrieben wurde bzw. man will den verdeckte virtuellen Constructor explizit aufrufen. Wenn ein Aufruf nicht gewollt ist, dann natürlich nicht. (ich hoffe damit habe ich alle Möglichkeiten abgedeckt).

Danke!

/EDIT: Ok, dann eine Frage dazu: TGraphic führt einen virtuellen Constructor ein, aber warum wird innerhalb dessen denn "Inherited Create" aufgerufen?

Hawkeye219 14. Dez 2006 18:44

Re: Wann ein "inherited" im Constructor ?
 
Eigentlich wollte ich diese Aussage widerlegen:

Zitat:

Zitat von Muetze1
Afair ist ohne einen virtuellen Constructor auch kein Zwang da, inherited auf zu rufen.

Ein Beispiel:

Delphi-Quellcode:
type
  TMyPen = class (TPen)
  public
    constructor Create;
  end;

constructor TMyPen.Create;
begin
  inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Pen : TMyPen;
begin
  Pen := TMyPen.Create;
  Pen.Color := clRed; // ohne INHERITED in TMyPen.Create knallt es hier...
  Pen.Free;
end;
Zu deiner TGraphic-Frage:

Zitat:

Zitat von Graphics.pas von Delphi 6
Delphi-Quellcode:
constructor TGraphic.Create;
begin                // This stub is required for C++ compatibility.
  inherited Create;  // C++ doesn't support abstract virtual constructors.
end;

Gruß Hawkeye

marabu 14. Dez 2006 19:00

Re: Wann ein "inherited" im Constructor ?
 
Hallo,

nur wegen dem Borland Kommentar im Zitat von Hawkeye: der Object Pascal Compiler kennt zwar abstrakte virtuelle Konstruktoren - aber zur Laufzeit knallt es auf jeden Fall beim Aufruf von inherited im Konstruktor einer abgeleiteten Klasse. Irgendwie unbrauchbar.

Freundliche Grüße

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:22 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