Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Create wird nicht aufgerufen bei Klassen-Chaos (https://www.delphipraxis.net/60891-create-wird-nicht-aufgerufen-bei-klassen-chaos.html)

Khabarakh 13. Jan 2006 20:17

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Zitat:

Zitat von Muetze1
Es muss vor allem nur ein virtueller Constructor Create definiert werden in der TImport_Virtual - kein abstrakter!

Die Ableitungen müssen ihn überschreiben und dann wird dieser auch aufgerufen...

Warum _muss_ der Konstruktor virtuell sein? Wenn die Basisklasse rein abstrakt ist und nicht irgendwelche Felder befüllen muss, kann der Konstruktor doch auch abstrakt sein.
Zitat:

Zitat von tomsel
Genau! Die Variable "Import" ist ja wohl vom Typ TImport_Virtual. Da TImport_Virtual den Construktor von TObject nicht überschreiben kann, ihn aber auch nicht verdeckt, wird halt TObject.Create aufgerufen.

Aha, und TObject.Create wirft dann eine EAbstractError-Exception :roll: . Natürlich wird der Konstruktor von TObject wie jede andere Methode von einem gleichnamigen Konstruktor (egal ob abstrakt oder nicht) verdeckt.

Muetze1 13. Jan 2006 20:48

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von Muetze1
Es muss vor allem nur ein virtueller Constructor Create definiert werden in der TImport_Virtual - kein abstrakter!

Die Ableitungen müssen ihn überschreiben und dann wird dieser auch aufgerufen...

Warum _muss_ der Konstruktor virtuell sein? Wenn die Basisklasse rein abstrakt ist und nicht irgendwelche Felder befüllen muss, kann der Konstruktor doch auch abstrakt sein.

Könnte er, aber das wäre so wie eine vorhandene, implementierte Methode in einer Ableitung der Klasse als abstrakt zu deklarieren und somit die vorhandene Implementation wegzuschmeissen. Abstrakt soll die Ableitungen zwingen bestimmte Methoden zu implementieren und da es immer einen Konstruktor von TObject gibt und du ihn in einer Ableitung abstrakt machst, wie willst du diesen dann noch gross aufrufen, so dass dieser Speicherplatz reservieren kann und Daten initialisieren kann? Willst du in allen Ableitung von TImport_Virtual die Programmierer zwingen jeweils selber sich um die Speicheralloziierung und -initialisierung der Instanzen kümmern?

Grundlegend ist es unlogisch und eigentlich sollte Delphi auch einen Fehler bringen bei dem gleichen Weg mit einer Methode anstatt eines Constructors. Aber durch die besondere Stellung des Konstruktors wird er es wohl akzeptieren, aber ich wage zu bezweifeln, dass er es mit einer Methode so mit sich machen lässt (Behauptung/Vermutung meinerseits ohne es jetzt nachzuprüfen).

Zitat:

Zitat von Khabarakh
Zitat:

Zitat von tomsel
Genau! Die Variable "Import" ist ja wohl vom Typ TImport_Virtual. Da TImport_Virtual den Construktor von TObject nicht überschreiben kann, ihn aber auch nicht verdeckt, wird halt TObject.Create aufgerufen.

Aha, und TObject.Create wirft dann eine EAbstractError-Exception :roll: . Natürlich wird der Konstruktor von TObject wie jede andere Methode von einem gleichnamigen Konstruktor (egal ob abstrakt oder nicht) verdeckt.

verdeckt, aber nicht überschrieben. Da die Metaklasse so definiert wurde:
Delphi-Quellcode:
 TImportClassType = class of TImport_Virtual;
Wird in deinem Falle immer TImport_Virtual.Create aufgerufen, aber nie der Konstruktor der Ableitung, da dieser nur durch ein überschreiben (sprich dynamischer/virtueller Konstruktor) aufgerufen wird. Durch das überschreiben wird die Methode der am höchsten entwickelten Klasse (von dem Basistyp TImport_Virtual ausgehend spezialisiserter) aufgerufen, da die Konstruktoren durch das überschreiben die alten in der VMT ersetzen. Beim verdecken bzw. definieren eines Constructors ohne irgendwas wird keine Ersetzung durchgeführt.

tomsel 13. Jan 2006 21:33

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von tomsel
Genau! Die Variable "Import" ist ja wohl vom Typ TImport_Virtual. Da TImport_Virtual den Construktor von TObject nicht überschreiben kann, ihn aber auch nicht verdeckt, wird halt TObject.Create aufgerufen.

Aha, und TObject.Create wirft dann eine EAbstractError-Exception :roll: . Natürlich wird der Konstruktor von TObject wie jede andere Methode von einem gleichnamigen Konstruktor (egal ob abstrakt oder nicht) verdeckt.

Ja, klar. Das hab ich übersehen:
Zitat:

...und wenn ich in der Basisklasse auch ein virtual; abstract; Create einfüge...
Erst Thread genau lesen!!! :duck:

Khabarakh 13. Jan 2006 21:38

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Zitat:

Zitat von Muetze1
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von Muetze1
Es muss vor allem nur ein virtueller Constructor Create definiert werden in der TImport_Virtual - kein abstrakter!

Die Ableitungen müssen ihn überschreiben und dann wird dieser auch aufgerufen...

Warum _muss_ der Konstruktor virtuell sein? Wenn die Basisklasse rein abstrakt ist und nicht irgendwelche Felder befüllen muss, kann der Konstruktor doch auch abstrakt sein.

Könnte er, aber das wäre so wie eine vorhandene, implementierte Methode in einer Ableitung der Klasse als abstrakt zu deklarieren und somit die vorhandene Implementation wegzuschmeissen. Abstrakt soll die Ableitungen zwingen bestimmte Methoden zu implementieren und da es immer einen Konstruktor von TObject gibt und du ihn in einer Ableitung abstrakt machst, wie willst du diesen dann noch gross aufrufen, so dass dieser Speicherplatz reservieren kann und Daten initialisieren kann?

Wirf mal einen Blick in den VCL-Quellcode :wink: . Der Konstruktor von TObject als Methode an sich hat überhaupt nichts mit Alloziierung zu tun (besser gesagt: er ist einfach leer), man kann ihn getrost weglassen. Ihn trotzdem aufzurufen kann zwar nicht schaden und kann man auch zu gutem Code-Style zählen, aber ein abstrakter Konstruktor ist eben problemlos möglich und auch sinnvoll. Wenn der Programmierer versucht, aus Versehen die abstrakte Basisklasse zu instanziieren, wird er gleich mit einer Exception getadelt :wink: (wenigstens ein kleiner Nachbau der sinnvollen abstrakten Klassen von .NET). Bei einer anderen Basisklasse gibt es dann immer noch virtual (wobei eine Abstrahierung einer spezialisierten Klasse meist wenig sinnvoll ist).

Zitat:

Grundlegend ist es unlogisch und eigentlich sollte Delphi auch einen Fehler bringen bei dem gleichen Weg mit einer Methode anstatt eines Constructors. Aber durch die besondere Stellung des Konstruktors wird er es wohl akzeptieren, aber ich wage zu bezweifeln, dass er es mit einer Methode so mit sich machen lässt (Behauptung/Vermutung meinerseits ohne es jetzt nachzuprüfen).
Meinst du damit, eine Methode mit eine abstrakten zu überdecken? Wie ich oben schon geschrieben hab, warum sollte das nicht möglich sein? Eine abstrakte Methode ist erst einmal einfach eine Methode, und diese verdeckt eben gleichnamige geerbte Member. Das mag nicht immer sinnvoll, bei einer leeren überdeckten Methode aber sich nicht verwerflich sondern wie oben gezeigt sogar nützlich sein.

Zitat:

Zitat:

Zitat von Khabarakh
Zitat:

Zitat von tomsel
Genau! Die Variable "Import" ist ja wohl vom Typ TImport_Virtual. Da TImport_Virtual den Construktor von TObject nicht überschreiben kann, ihn aber auch nicht verdeckt, wird halt TObject.Create aufgerufen.

Aha, und TObject.Create wirft dann eine EAbstractError-Exception :roll: . Natürlich wird der Konstruktor von TObject wie jede andere Methode von einem gleichnamigen Konstruktor (egal ob abstrakt oder nicht) verdeckt.

verdeckt, aber nicht überschrieben.
Ja. Das habe ich so geschrieben und auch so gemeint :wink: .
Zitat:

Da die Metaklasse so definiert wurde:
Delphi-Quellcode:
 TImportClassType = class of TImport_Virtual;
Wird in deinem Falle immer TImport_Virtual.Create aufgerufen, aber nie der Konstruktor der Ableitung, da dieser nur durch ein überschreiben (sprich dynamischer/virtueller Konstruktor) aufgerufen wird.
Beziehst du dich auf den ersten Post? Denn mittlerweile hat glkgereon ja seinen Konstruktor abstrakt deklariert und überschrieben (auch wenn er irgendwo noch einen Fehler haben muss :zwinker: ).

glkgereon 13. Jan 2006 22:15

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Jetzt funktioniert es so:

Delphi-Quellcode:
type
  TImport_Virtual = class(TObject)
  private //Basisklasse für ImportTyp
    FFileName: String;
    FFileExt: String;
  public
    FData: TDataArray;
    constructor Create; virtual; abstract;
    destructor Destroy; virtual; abstract;
    function OpenFile(var Err: String):Boolean; virtual; abstract;
    function CloseFile(var Err: String):Boolean; virtual; abstract;
    function Analyse(var Err: String):Boolean; virtual; abstract;
    function GetData(var Dat: TDataArray):Boolean;
    property FileName: String read FFileName write FFileName;
  end;

  TImportClassType = class of TImport_Virtual;

  TDBFImport = class(TImport_Virtual)
  private //Import aus DBF-Datei
    FDBF: TDBFFile;
  public
    constructor Create; override;
    destructor Destroy; override;
    function OpenFile(var Err: String):Boolean; override;
    function CloseFile(var Err: String):Boolean; override;
    function Analyse(var Err: String):Boolean; override;
  end;
aber man darf dann im Create nicht inherited Create; aufrufen ;)

omata 13. Jan 2006 22:19

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Cool,

äh was hatte ich noch in meinem ersten Post geschrieben?

MfG
Thorsten

Khabarakh 13. Jan 2006 22:23

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Zitat:

Zitat von glkgereon
Delphi-Quellcode:
    destructor Destroy; virtual; abstract;

Achtung: Destroy ist schon in TObject als virtual deklariert, lass diese Zeile einfach weg. Sonst wird z.B. dein Destruktor nicht bei einem Aufruf von Free aufgerufen.

Zitat:

aber man darf dann im Create nicht inherited Create; aufrufen ;)
War das der Fehler von vorhin :mrgreen: ?

glkgereon 14. Jan 2006 09:33

Re: Create wird nicht aufgerufen bei Klassen-Chaos
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von glkgereon
Delphi-Quellcode:
    destructor Destroy; virtual; abstract;

Achtung: Destroy ist schon in TObject als virtual deklariert, lass diese Zeile einfach weg. Sonst wird z.B. dein Destruktor nicht bei einem Aufruf von Free aufgerufen.

Ok, mach ich :)

Zitat:

Zitat:

aber man darf dann im Create nicht inherited Create; aufrufen ;)
War das der Fehler von vorhin :mrgreen: ?
Ja :mrgreen:


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

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz