![]() |
Konstruktoren in Delphi
Guten Tag,
Kann mir jemand erklären wie die ganze Konstruktoren Geschichte in Delphi funktioniert ? Ich blicke da einfach nicht durch. Ich habe ein neues VCL-Form erstellt und möchte nun einen eigenen Konstruktor erstellen:
Delphi-Quellcode:
1. Warum muss hier Create(self) angegeben werden ? Warum reicht Inherited; nicht aus ?
public
{ Public-Deklarationen } Constructor Create(_pnlColor:TColor;_pnlTitle:String;_memoContent:TStringList); //.... constructor TFehler.Create(_pnlColor: TColor; _pnlTitle: String; _memoContent: TStringList); begin Inherited Create(self); //1 setPanelTitle(_pnlTitle); setPanelTitleColor(_pnlColor); fillMemo(_memoContent); end; Ich verstehe das so: Inherited muss benutzt werden damit der Standard-Konstruktor aufgerufen wird. Wenn ich Inherited nicht verwenden würde, dann würde mein VLC-Formular nicht erstellt werden. 2. Wann werden folgende Schlüsselwörter benötigt.
3. Wie erstelle ich einen eigenen Konstruktor ohne Parameter ? Ich möchte noch bestimmte Werte setzten, wenn das Objekt erstellt wird. Im Beispiel ![]() Dies begreife ich nicht. Ein override; würde für mich mehr Sinn ergeben. Ich möchte ja einen eigenen Standard-Constructor erstellen sonst würden ja zwei gleiche exisieren:
Delphi-Quellcode:
Somit existiert hier ja:
type
// Define a parent class, base on TObject by default TFruit = class public name : string; Constructor Create; overload; // This constructor uses defaults Constructor Create(name : string); overload; end; constructor TFruit.Create; begin Inherited; //Setze Initial-Werte... end;
Delphi-Quellcode:
Wie weis Delphi nun welchen Create; Konstruktor genommen werden soll ?
Create; //Standard-Konstruktor
Create; //Überladener-Konstruktor Create(name:String); overload; //Überladener-Konstruktor was ok ist weil durch die parameter kann der Konstruktor vom anderen unterschieden werden Danke für die Hilfe. Gruss Int3g3r |
AW: Konstruktoren in Delphi
Ich empfehle dringend ein Tutorial zur OOP mit Delphi.
Zur Detailfrage zum Thema Überladen: Delphi erkennt die korrekte Methode anhand der Parametersignatur des Aufrufs. Das merkt man spätestens dann, wenn man mit zwei identischen Signaturen überladen möchte. Signatur ist hier übrigens eine vornehmes Wort für Parameterliste. Daraus folgt übrigens, daß die beiden Create-Aufrufe ohne Parameter nicht zwei verschiedene Methoden aufrufen werden, sondern beide die gleiche, das was da steht ist also falsch. Sherlock |
AW: Konstruktoren in Delphi
1. Wen TFehler ein Formular ist, dann gibst du mit inherited Create(...) den Owner an. Also die Komponente/Formular, was dieses Formular wieder freigeben soll.
Hier Self mitzugeben ist Quark. 2. Es gilt: override - Überschreiben einer virtuellen Methode/Konstruktor/Destruktor; overload - Ich habe mehrere gleichnamige Methoden, die sich anhand ihrer Parameter unterscheiden (keine, ein Parameter, bis N-Parameter). reintroduce - Ich möchte, dass meine Klasse und seine Ableitungen diese Methode nehmen und nicht die gleiche Methode aus der Elternklasse. virtual - Nachkommenklassen sollen diese Methode überschreiben (override) können und weiteres Verhalten ergänzen. 3. Genau so wie, wie du es im verlinkten Beispiel siehst:
Delphi-Quellcode:
4. Ohne Argumente wird der überladene Konstruktor der Klasse .genommen
type
// Define a parent class, base on TObject by default TFruit = class public name : string; Constructor Create; overload; // This constructor uses defaults Constructor Create(name : string); overload; end; ... // Create a fruit object - parameterless version constructor TFruit.Create; begin // Execute the parent (TObject) constructor first inherited; // Call the parent Create method // Now set a default fruit name self.name := 'Fruit'; <--------------------------- Da kommt dein "Ich möchte noch bestimmte Werte setzten, wenn das Objekt erstellt wird." end; |
AW: Konstruktoren in Delphi
Zitat:
Dies ist ein eigenständiges Formular, also es hat keinen Owner. Danke für die Hilfe |
AW: Konstruktoren in Delphi
Wenn es keinen Owner hat, dann ist der Owner wohl
Delphi-Quellcode:
.
nil
|
AW: Konstruktoren in Delphi
Vielen Dank an alle.
Ich habe jetzt meine Konstruktoren wie im ![]() Wo liegt mein Fehler ?
Delphi-Quellcode:
Meldungen/Fehler beim kompilieren:
public
{ Public-Deklarationen } Constructor Create; overload; Constructor Create(_pnlColor:TColor;_pnlTitle:String;_memoContent:TStringList); overload; end; //....... constructor TFehler.Create(_pnlColor: TColor; _pnlTitle: String;_memoContent: TStringList); begin Inherited Create(nil); setPanelTitle(_pnlTitle); setPanelTitleColor(_pnlColor); fillMemo(_memoContent); end; constructor TFehler.Create; begin Inherited; // Fehler E2008 end; [dcc32 Warnung] form_CSVException.pas(24): W1010 Methode 'Create' verbirgt virtuelle Methode vom Basistyp 'TCustomForm' [dcc32 Warnung] form_CSVException.pas(25): W1010 Methode 'Create' verbirgt virtuelle Methode vom Basistyp 'TCustomForm' [dcc32 Fehler] form_CSVException.pas(53): E2008 Inkompatible Typen - Warum erhalte ich den Fehler E2008 ? Wie lässt sich dieser beheben ? - Wie lassen sich die Warungen beheben ? |
AW: Konstruktoren in Delphi
Probier es mal so
Delphi-Quellcode:
public
{ Public-Deklarationen } Constructor Create; reintroduce; overload; Constructor Create(_pnlColor:TColor;_pnlTitle:String;_memoContent:TStringList); reintroduce; overload; end; //....... constructor TFehler.Create; begin Inherited Create(nil); end; constructor TFehler.Create(_pnlColor: TColor; _pnlTitle: String;_memoContent: TStringList); begin Create(); // ruft TFehler.Create() auf setPanelTitle(_pnlTitle); setPanelTitleColor(_pnlColor); fillMemo(_memoContent); end; |
AW: Konstruktoren in Delphi
Zitat:
Warum funktioniert es nicht wie es im Beispiel steht ? Was ist mit den Warnugen ? Danke! |
AW: Konstruktoren in Delphi
Es funktioniert so wie im Beispiel, soweit das Beispiel hier auch zutrifft.
Welche Warnungen? Es dürften keine Warnungen mehr da sein. |
AW: Konstruktoren in Delphi
Zitat:
Du musst dich dann zwingend selbst um die Freigabe kümmern. Nur wenn dein Form (TFehler) immer modal in einen try finally mit Freigabe aufgerufen wird, könnte man es akzeptieren. Machen würde ich es dennoch nicht. Bei mir haben alle Konstruktoren eines TForms alse ersten Parameter AOwner... Der Aufruf zum Erzeugen kann dann TFehler.Create(Nil, Color...) oder TFehler.Create(Application, Color...) etc. sein. Frank |
AW: Konstruktoren in Delphi
Zitat:
Oder im OnDestroy freigeben. Das wären alles gültige Alternativen. |
AW: Konstruktoren in Delphi
Besten Dank für die Antworten.
Leider blicke ich immer noch nicht durch bei den Konstruktoren/Destruktoren. Z.b
Delphi-Quellcode:
4) Wann ist ein "Inherited" notwenig im Konstruktor/Dekonstruktor ? Sobald von einer Klasse geerbt wird, richtig ?
type
TMail = Class smtp: TIdSMTP; sslIOHandler: TIdSSLIOHandlerSocketOpenSSL; private // Private public // Public constructor Create(param1, param2 : String); destructor Destroy; end; var Mail : TMail; implementation constructor TMail.Create(param1, param2 : String); begin smtp := TIdSMTP.Create(nil); sslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); end; destructor TMail.Destroy; begin if Assigned(smtp) then FreeAndNil(smtp); if Assigned(sslIOHandler) then FreeAndNil(sslIOHandler); end;
Delphi-Quellcode:
.
TMail = Class(TComponent) // Hier währe ein Inherited dann notwendig, richtig ?
5) Wie bei meinem Beispiel zu sehen habe ich keinen "Standard-Konstruktor" erstellt. Meine Klasse soll nur mit diesem Konstruktor mit Parameter instanziert werden können. Bei C# ist ein Standardkonstruktor notwendig, ist das bei Delphi auch der Fall ? 6) Das Beispiel oben lässt sich kompillieren und instanzieren. Leider verstehe ich aber nicht warum bei
Delphi-Quellcode:
der Destruktor nicht abgehandelt wird.
Mail.Free
Ich erzeuge Memory-Leaks, was mache ich falsch ? Lösung zu 6)
Delphi-Quellcode:
destructor Destroy; override;
Gruss Int3g3r PS: Um Memory-Leaks zu Prüfen folgende Zeile beim Projekt->Quelltext einfügen
Delphi-Quellcode:
ReportMemoryLeaksOnShutdown := True;
|
AW: Konstruktoren in Delphi
Zitat:
Delphi-Quellcode:
in den Konstruktor und Destruktor, bei ersterem (in aller Regel) am Anfang, im Destruktor ans Ende. Jede Klasse erbt von irgendeiner Basisklasse, und wenn es nur TObject ist, die zwar einen leeren Konstruktor hat, aber vielleicht ändert sich das mal.
inherited;
Zitat:
Delphi-Quellcode:
markieren. IIRC verhindert das aber nicht, den Konstruktor der Basisklasse zu nutzen.
overload; reintroduce;
Zitat:
Zitat:
Delphi-Quellcode:
markiert werden, damit der der abgeleiteten Klasse gerufen wird, nicht der der Basisklasse. Tut man das nicht, gibt der Compiler eine Warnung, soweit ich weiß.
override;
Grüße Dalai |
AW: Konstruktoren in Delphi
Jupp, beim DESTRUCTOR immer das OVERRIDE.
Teilweise auch beim CONSTRUCTOR. * siehe TComponent, wenn die Komponente zur DesignTime auf die Form soll, denn der DFM-Loader kennt nur "sein" Create. * Es gibt zwar einen leeren Standard-Constructor in TObject, aber der muss nicht aufgerufen werden. (besser ist es aber, wenn er wird) * * denn aktuell ist der eh leer * * VOR dem Create (oder wie auch immer man das nennen mag) wird bei einem "CONSTRUCTOR" immer erstmal die Speicherinitialisierung durchgeführt, also vor dem Inhalt dies Create INHERITED einach immer. * wenn es nicht nötig ist, weil es nichts im Vorfahren gibt, dann ignoriert es der Compiler * ansonsten ruft es die "gleichnamige" Methode mit den "gleichen" Parametern im Vorfahren auf (bzw. die Methode mit dem Namen den man angibt) Am Einfachsten/Sinnvollsten ist es das INHERITED bei "erstellenden" Methoden (Create/Get/...) als Erstes auszuführen und bei löschenden/freigebenden Methoden (Destroy/Delete/...) als Letztes. (Ausnahmen gibt es, aber meistens ist es so am Besten) Im Delphi gibt es immer per Standard ein "leeres" Create. * Wenn man nichts initialisieren will, dann braucht man also keinen Eigenen * genauso beim DESCRUCTOR (hier gibt es im Delphi nur den "Destroy", welcher automatisch aufgerufen wird) * * hat man nichts freizugeben, oder alles wird automatisch freigegeben (z.B. String, dyn. Array, Interface oder Variant), dann braucht man hier auch keinen eigenen DESTRUCTOR Im Free/FreeAndNil ist bereits ein "if Assigned" eingebaut, also nochmal ist nicht nötig. (doppelt ist nicht falsch, nur unnötig)
Delphi-Quellcode:
Hier wird automatisch Speicherverwaltet, daher ist für diese beiden Felder/Variablen kein Destructor nötig.
type
TMail = class(TComponent) ... constructor TMail.Create(param1, param2 : String); begin inherited Create(nil); // NIL: oder du baust den Owner auch in dein Create mit ein smtp := TIdSMTP.Create(Self); sslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Self); end; Das Inherite bei diesem Creaate(nil) ist nicht unbedingt nötig. * mit inherited wird immer das Create(mit TComponent) im Vorfahren aufgerufen * ohne inherited in deiner Klasse (sollte es dort so ein Create geben), ansonsten im Vorfahren |
AW: Konstruktoren in Delphi
Danke für die weiteren Antworten.
Zitat:
Delphi-Quellcode:
schreibe erbt diese automatisch von TObject ?
TMail = Class
Zitat:
Nun habe ich noch eine weitere Frage. Wie lässt sich der Owner in meinem Beispiel einbauen, bzw macht dies überhaupt Sinn ?
Delphi-Quellcode:
Ich kann bei
constructor TMail.Create(AOwner: TComponent, param1, param2 : String);
begin inherited Create; smtp := TIdSMTP.Create(nil); sslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); end;
Delphi-Quellcode:
keinen Owner angeben da meine Klasse von TObject erbt.
inherited Create;
Das Create von TObject will keine Parameter. Bzw was soll ich danach mit dem Owner anstellen wenn ich diesen im TMail.Create übergebe ? Gruss Int3g3r. |
AW: Konstruktoren in Delphi
Zitat:
Delphi-Quellcode:
ist dasselbe wie
TMail = Class
Delphi-Quellcode:
.
TMail = Class(TObject)
Zitat:
Grüße Dalai |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:10 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