AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Konstruktor Create Virtual oder nicht?

Ein Thema von smudo · begonnen am 29. Aug 2007 · letzter Beitrag vom 23. Sep 2008
Antwort Antwort
Seite 2 von 4     12 34      
PMM

Registriert seit: 17. Feb 2005
101 Beiträge
 
#11

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 15:41
Vieleicht hilft folgendes weiter: Der Konstruktor wird ja aufgerufen, bevor das Objekt existiert- das soll ja gerade erzeugt werden. Es gibt also noch gar kein Instanz die bestimmen könnte, welche evtl. überschriebene Methode aufzurufen ist. Bei allen anderen Methoden ist das anders: da gibt es ja schon ein Objekt das bestimmen kann, welche konkrete Methode zur Laufzeit gemeint ist.
PMM
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 16:10
Zitat:
Der Konstruktor wird ja aufgerufen, bevor das Objekt existiert-
Falsch der Konstruktor wird aufgerufen nachdem das Objekt auf dem Speicher erzeugt und initaisiert wurde damit man in seinem eigenen Konstruktor diese Instance noch weiter initialisieren kann. Ist der Konstruktor dabei virtuell und override deklariert wurden dann kann man mit Hilfe eines dynamischen Klassentypes der Vorfahrklasse in einer Variable auch eine Instance der abgeleiteten Klasse als Instance erzeugen. Deshalb machen virtuelle Konstruktoren auch einen Sinn.

Delphi-Quellcode:
type
  TBaseClass = class(TObject)
    constructor Create(const BaseClassParameter); virtual;
  end;

  TBaseClassClass = class of TBaseClass;

  TSecondClass = class(TBaseClass)
    constructor Create(const BaseClassParameter); override;
  end;

procedure Test;
var
  BaseClass: TBaseClassClass;
begin
  BaseClass := TBaseClass;
  with BaseClass.Create(Params) do Free;

  ShowMesssage(BaseClass.ClassName);


  BaseClass := TSecondClass;
  with BaseClass.Create(Params) do Free;
  
  ShowMesssage(BaseClass.ClassName);
end;
Eine Variable BaseClass enthält den Klassetyp den man dynamisch zu Laufzeit erzeugen möchte. Die Regeln der Klassevererbung herrschen also auch bei Klassenvariablen und Klassenmethoden. Beim Konstruktor ist nun wichtig das er virtuell ist damit man unabhängig von der realen Klasse in der Variablen BaseClass auch dynamisch eine Instanz erzeugen kann.

Manche bezeichnen das als Metaklassen. Wichtig ist nur zu wissen das es ohne diese Feature, also auch der Möglichkeit von virtuellen Konstruktoren in diesem Zusammenhang die Streaming-Fähigkeiten der VCL garnicht umsetzbar wären. Alsodas Speihcern und Laden von Komponenten samt TForm in einen Stream als DFM Resource/Datei. Auch die TGraphic Objecte würden als Ganzes nicht die gewohnte Funktionalität bieten.

Die Möglichkeit für virtuelle Konstruktoren sind also ein MUSS !

Nochwas zur Erstellungsreiehenfolge von Instancen:

1.) .InstanceSize wird aufgerufen um die Größe des Speichers des Objektes zu ermitteln
2.) .InitInstance wrd aufgerufen um kompexe Datenstrukturen die als Felder im Objekt deklariert wurden zu initlaisieren
3.) erst jetzt wird der Konstruktor aufgerufen der seinerseit eventuell inherited Konstruktor aufruft
4.) .AfterConstruction wird aufgerufen

Gruß Hagen
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#13

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 16:44
Zitat von PMM:
Vieleicht hilft folgendes weiter: Der Konstruktor wird ja aufgerufen, bevor das Objekt existiert- das soll ja gerade erzeugt werden. Es gibt also noch gar kein Instanz die bestimmen könnte, welche evtl. überschriebene Methode aufzurufen ist.
Dadurch dass er die überschriebenen Constructoren etc aus der VMT ermittelt kann er dies auch ohne Instanz, schliesslich ist diese in den Klasseninformationen abgelegt, welche er mit dem Klassennamen (bzw. das was in den von negaH erklärten Metaklassen Variablen enthalten ist (ein Zeiger auf diese Information)) bekommt und somit nachschauen kann.

Sehe ich das so richig, negaH? Ich frage in letzter Zeit lieber nochmal nach...
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 17:57
Jain. In der Klassenstruktur steht zwar ein Zeiger auf den aktuell implementierenden Konstruktor der Klasse, Konstruktoren sind damit per se immer virtuell Das steht nicht in der VMT -> virtual Method Table, diese ist nur einer der Bestandteile einer heutigen Klassenstruktur. Siehe System.pas.

aber !

Wir möchten dynamisch zur Laufzeit erst die zu erzeugende Klassse definieren, wie im Beispiel ob TBaseClass und/oder TSecondClass. Damit man beiden Klassen auf diese Art&Weise erzeugen kann und auch Paramater dieser Klassen übergeben kann muß man nit explizit virtuell deklarierten Klassen arbeiten.

Macht man die nicht so würde im 2. Aufruf in der BaseClass den Klassentyp TSecondClass enthält nicht der Constructor von TSecondClass aufgerufen sondern derjenjge Konstruktor der über

type
TBaseCLass = class of TBaseClass

deklariert wurde. Im zweiten Aufruf würde man also Konstruktor TBaseClass.Create aufrufen aber eine Instance vom Typ TSecondClass erhalten ! Hat man nun im Konstruktor von TSecondClass eigene individuelle Implementierungen vorgesehen so würden diese eben nicht ausgeführt werden. Man erzeugt eine Instance vom Typ TSecondClass ruft aber TBaseClass.Create auf.

Probierts einfach aus. In den obigen 2 Klasen im Konstruktor eine ShowMessage(ClassName) rein. Dann als 1. den Konstruktor nicht virtual deklarieren und den Test Code von oben starten. Es muß 2 mal "TBaseClass" angezeigt werden obwohl wir einmal eine Instance von TBaseClass und einmal von TSecondClass erzeugt haben. Dann alles virtuell machen. Nun geht so wir gewünscht.

Metaklassen können meistens nur dann sinnvoll benutzt werden wenn deren Konstruktor als virtual deklariert wurde. So wie bei TComponent.Create(AOwner: TComponent);

Metaklassen, ich mag diese Wort nicht für diese Art der OOP. Es gibt defakto keine Unterscheidung zwischen diesen Metaklassen, also der Benutzung von typisierten Klassenvariablen -> type class of Class, zu der Benutzung vin Klassen im Allgemeinen. Die Deklaration/Benutzung von Klassen ist genauso OOP wie die Deklaration/Benutzung von typsisierten Klassen-Variablen oder von typisierten Instanzen einer Klasse, kurz Objekten. Alles sind Features der OOP, Metaklassen suggeriert was falsches und ist eine Marketingschpfung, selbst wenn sich nur ein schlauer Programmierer damit besser verkaufen möchte.

Metaklassen sind nichts anderes als Klassenvariablen um dynamisch den Typ der zu erzeugenden Instanzeklasse festlegen zu können.
Der Typ so einer Klassevariablen ist immer ein

type class of Class; Diese Deklaraton suggeriert das man einen Klasentyp zu einer Klassenhierarchie als Überbau deklariert, sprich eine Metaklasse. Das ist Quatsch. Man deklariert einen neuen Datentyp vom Typ Pointer der aber typisiert nur Klassen aufnehmen kann die von de Basis Klasse abgleietet wurden. Wenn es eine Metaklasse wäre dann könnte man mit TBaseClassClass.Create() auch eine Meta-Instance also Meta-Objekt dieser Metaklasse erzeugen.

Es sind typsierte Klassenvariablen und definitiv eine Grundlage für die Polymorphie der Klassen. Es ist Polymorph af Klassenebene weil in der Variablen "BaseClass"

1.) nur typisierte und von der Mutterklasse TBaseClass abgeleitete Klassen gespeichert werden können. Der Compiler wird einen Fehler bringen wenn man was anders versucht.
2.) alle dynamisch zur Laufzeit veränderlich ist, also immer ein anderes Gesicht annehmen kann, ja nach Klassentyp den man in dieser Variable speichert
3.) eben Zeiger auf eine Klasse, und das ist ein hardcoded Recordstruktur im Codesegement die eine Klasse beschreibt, speichert.

Gruß Hagen

[edit]ähm sorry für meine Tippfehler, das trainiert eure Intelligenz, seht's positiv [/edit]
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#15

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 21:25
So, jetzt muss ich auch noch mal meinen Senf dazu geben.
Zitat:
In der Klassenstruktur steht zwar ein Zeiger auf den aktuell implementierenden Konstruktor der Klasse, Konstruktoren sind damit per se immer virtuell
Das verstehe ich gerade überhaupt nicht. Wieso sind Konstruktoren "automatisch" virtuell? Ich habe mich mal ziemlich weit in die VMT eingegraben, einen Zeiger auf den aktuell implementierenden Konstruktor habe ich nicht gefunden...

Zitat:
ShowMessage(ClassName) rein. Dann als 1. den Konstruktor nicht virtual deklarieren und den Test Code von oben starten. Es muß 2 mal "TBaseClass" angezeigt werden obwohl wir einmal eine Instance von TBaseClass und einmal von TSecondClass erzeugt haben.
Du hast doch eben erklärt, dass wir eine TSecondclass-Instanz erstellt haben, folglich zeigt ClassName auch TSecondclass an, da Classname auf der VMT beruht, die nun mal TSecondclass ist. Wir würden 'TBaseClass' erhalten, wenn wir ein showmessage mit dem hartcodierten Klassennamen in beiden Konstruktoren seperat aufrufen würden.

Zitat:
Metaklassen können meistens nur dann sinnvoll benutzt werden wenn deren Konstruktor als virtual deklariert wurde. So wie bei TComponent.Create(AOwner: TComponent);
Nur der Vollständigkeit halber: Mit Klassenmethoden geht's natürlich auch.

Zitat:
Metaklassen, ich mag diese Wort nicht für diese Art der OOP.
Deshalb wird das ganze in der Delphi-Hilfe auch "Klassenreferenztyp" genannt. Im Gegensatz zu anderen Programmierklasse handelt es sich in Delphi ja nicht um eine Klasse, weshalb auch ich diesen Begriff treffender finde.
Das ist auch etwas, was Delphi hat, C++ jedoch nicht. In C++ wäre es ein rein logischer Widerspruch, da dort Klassenmethoden als "static" deklariert werden, und das beißt sich mit "virtual".

Genug geschreibselt. Ich hoffe, ich habe nicht nur Müll erzählt.
Gute Nacht
Apollonius
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 22:26
Zitat:
Das verstehe ich gerade überhaupt nicht. Wieso sind Konstruktoren "automatisch" virtuell? Ich habe mich mal ziemlich weit in die VMT eingegraben, einen Zeiger auf den aktuell implementierenden Konstruktor habe ich nicht gefunden...
Ok, was unterscheidet primär eine statische Methode von einer virtuellen/dynamsichen Methode ?

Die statische Methode muß nicht überschrieben werden, sie exitiert statisch für alle Klassen der nachfolgenden Hierarchie der abgeleiteten Klassen und es ist immer die gleiche Methode. Dadurch besteht nicht die Notwendigkeit in der Klassenstruktur einen Zeiger zu reservieren der individuell für die nachfolgenden Klassen veränderbar sein muß. Statische Methoden tauchen also in der Klassenstruktur/record im Codesegment garnicht auf.

Der Zeiger auf den Konstruktor einer Klasse findet sich aber in der Klassenstruktur, quasi als "Datenfeld". Somit kann eine abgeleitete Klasse diesen Zeiger auf eine andere Methode umdefinieren. Das ist virtuel und nicht statisch.
Da in den Delphi Klassen ein solcher Slot existiert für den Konstruktor wie auch Destructor sind diese per se virtuelle Methoden, auch wenn wir sie nicht explizit als virtuell deklarieren.

Deklarieren wir eine virtuell Methode in einer Klasse so wird in der dazugehörigen Klassenstruktur in deren VMT=virtual Method Table am Ende dieser geerbten und vom Vorgänger 1 zu 1 kopierten VMT diese neue Klassenbezogene VMT um einen neuen Slot für diese neue virtuelle Methode reserviert. Darin steht der Zeiger auf unsere Methode. Die VMT einer Klassenhierarchie kann also immer nur additiv arbeiten, logisch da sich der Index einer einmal in einer Vorgängerklasse deklarierten virtuellen Methode in dieser VMT nie verändern darf. Nur so kann man sicherstellen das innerhalb einer überschriebenen virtuellen Methode das inherited auch funktioniert. Inherited kennt den Index/Offset der eigenen Methoden und schaut nun in der Parent.Class.VMT am gleichen Index nach, lädt den Zeiger der Methode und führt einen CALL dorthin durch. Das geht in der vorherigen überschriebenen Methoden mit inherited immer weiter bist zur Rootklasse die als erste diese virtuelle Methode deklariert hat. Ab diesem Moment ist die VMT der Parent Classe in ihrer Größe/Anzahl an VMT Slot kleiner. Dh. diese Vorgänger klasse enthlt diese in der Nachfolgeklasse deklarierte virtuelle Methode nicht in ihrer VMT.

Das bedeutet:

- VMT einer Klasse ist ein Array[] of Procedure
- eine Klasse erbt 1 zu 1 als Kopie die VMT ihrer Vorgängerklasse
- eine Klasse die neue virtuelle Methoden deklariert hängt diese neuen Slots an diese Kopie hinten dran
- damit wird der Speicherverbrauch im Codesegemt für diese Klassenstrukturen immer größer je mehr Klassen und mehr virtuelle Methoden man deklariert
- der Aufrufoverhead für virtuelle Methoden, inklusive des inherited Aufrufs, beschränkt sich auf einen indirekten CALL [Class.VMT.Index]
- die aktive Mitarbeit des Compilers ist von nöten. Man kann also nicht direkt zur Lauzeit die VMT benutzen um per Index eine virtuelle Methode aufzurufen. Dafür gibt es Compiler Makros VMTOffset() o.ä.
- in der VMT wird nicht hinterlegt wieviele Slots in der VMT gespeichert sind. Man kann also nicht direkt über die Klassenstruktur ermitteln wieviele virtuelle Methoden eine Klasse besitzt. Das geht aber über Umwege denoch Einfach mal in den Borland.Newsgroups nach meinem Posting mit VMTSlotOf() suchen.

Eine Instance einer Klasse enthält als ersten Zeiger in seiner Datenstruktur einen Zeiger direkt in die Klassenstruktur, also in die Mitte derselben. An dieser Addresse steht im Codesegement der VMT. Danach folgt die DMT = dynamic Method table.
Das hat zwei wichtige Gründe

1.) historisch bedingt. Die alten TObjecte aus Borland Pascal zeiten besaßen eine Klassenstruktur die direkt mit der VMT began. Damit die alten Objekte zu den neuen Klassen halbwegs kompatibel blieben hat man wohl diesen Weg gewählt.
2.) man kann so sehr schnell ausgehend von einem Instanzzeiger indirekt durch dessen Klassen.VMT eine virtuelle Methode anspringen

Nun die neue Klassenstruktur besitzt aber vor ihrer VMT, also mit negativem Offset noch weitere Felder. In diesen findest du auch die Einträge für den Konstruktor und Destruktor. Diese sind per se virtuell.

In System.pas findest du diese Konstanten

vmtSelfPtr = -76;
vmtIntfTable = -72;
vmtAutoTable = -68;
vmtInitTable = -64;
vmtTypeInfo = -60;
vmtFieldTable = -56;
vmtMethodTable = -52;
vmtDynamicTable = -48;
vmtClassName = -44;
vmtInstanceSize = -40;
vmtParent = -36;
vmtSafeCallException = -32;
vmtAfterConstruction = -28;
vmtBeforeDestruction = -24;
vmtDispatch = -20;
vmtDefaultHandler = -16;
vmtNewInstance = -12;
vmtFreeInstance = -8;
vmtDestroy = -4;

vmtQueryInterface = 0;
vmtAddRef = 4;
vmtRelease = 8;
vmtCreateObject = 12;

Nun eine Klassenstruktur sieht so aus

Delphi-Quellcode:
Class = packed record
 vmtSelfPtr = -76; // hm;) ein Sanitycheck, zeigt auf @VMT was gleichbedutend mit dem Klassenzeiger ist
  vmtIntfTable = -72; // Zeiger auf eine Tabelle in der die implementierten Interfaces dieser Klasse stehen
  vmtAutoTable = -68; //
  vmtInitTable = -64; // Zeiger auf Init Tabelle in dieser Struktur, dort steht welche Felder einer Instance autom. initialisert werden müssen und eben auch wie
  vmtTypeInfo = -60; // Zeiger auf die RTTI=Run Time Type Information dieser Klasse
  vmtFieldTable = -56;
  vmtMethodTable = -52;
  vmtDynamicTable = -48; // Zeiger auf @DMT
  vmtClassName = -44; // Zeiger auf den Klassennamen, folgt der DMT in dieser Struktur
  vmtInstanceSize = -40; // größe einer Instance dieser Klasse im Speicher
  vmtParent = -36; // SelfClass.ClassParent Vorfahrklasse
 
  vmtSafeCallException = -32; // ab hier alles Zeiger auf Methoden
  vmtAfterConstruction = -28;
  vmtBeforeDestruction = -24;
  vmtDispatch = -20;
  vmtDefaultHandler = -16;
  vmtNewInstance = -12;
  vmtFreeInstance = -8;
  vmtDestroy = -4; // zb. hier der Destruktor einer Klasse
  
  
  VMT: array[0..3] of procedure; // vmtQueryInterface, vmtAddRef, vmtRelease, vmtCreateObject <- Constructor !!
  DMT: packed record
         EntryCount: Word;
         Entries: array[EntryCount] of packed record
           SlotID: Word;
           Method: procedure;
         end;
       end;

  ClassName: ShortString;
  InterfaceTable: ....
... blabla
end;
ein Object zeigt nun direkt in diese Struktur an @VMT, PPointer(Instance)^ = Instance.ClassType = @Instance.ClassType.VMT


Wenn wir also zb. mit Pointer(TComponent)^ in das Codesegement zugreifen so finden wir dort @TComponent.VMT aus obiger Struktur.

Eine Klasse ist also ein Record im Codesegemt desjenigen Modules in das diejenige Unit eingelinkt wurde in der diese Klasse deklariert wurde. Das erklärt auch warum Packages funktionieren und warum die vielen Beispiele von TForms in DLL ohne Packages zu benutzen garnicht funktonieren können. Denn zb. der "as" oder "is" Operatior macht nichts anderes als Zeiger auf Klassen im Codesegemtn zu vergleichen.

Nun dieses Pamphlet könnte ich garantiert noch um das 4 fache verlängern, zb. was sind dynamsiche Methoden, was haben sie mit message methoden gemein, wie arbeiten diese, wie ist die Methodtable = publsiched Events und methoden aufgebaut, wie kann man aus dieser Tabelle alle Parameter deren Datentypen usw. ermitteln. Was macht die Interface Table, wir wird ein Interface-Zeiger einer Interface-Instance beim Aufruf einer ihrer Methoden in eine Object-Instance umgeserzt, als wie kommt man von einem Interface-Zeiger zu einem Object-Self-Zeiger damit man eine TObject als Basis für die Implementierung der Interfaces benutzen kann. Was steht so alles in der RTTI einer Klasse.

Wenn man nun noch die Historie kennt, also zb. seit Borland pascal 5 die Weiterentwicklung gerade dieser Internas mitverfolgen durfte so kann man

1.) sich ein Urteil über die abnehmende Qualität der Entwickler bei Borland in der nähren Vergangenheit erlauben
2.) man kann sehr gut erkennen wie mit jedem neuen Feature -> Delphi-Klassen -> Interfaces -> DispIntfs -> dyn. Message Methoden -> bishin zur RTTI, nach und nach in dieses Konzept eingebaut wurden.

Ich fands bisher spannend, naja in den letzten Jahren nicht mehr so sehr da sich ja nichts gravierendes mehr getan hat.

Gruß Hagen

PS: sorry für die Tippfehler, im dunkeln auf der Laptoptastur, sollte eure Intelligenz anregen mein Kauderwelsch.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Konstruktor Create Virtual oder nicht?

  Alt 29. Aug 2007, 22:31
Zitat:
u hast doch eben erklärt, dass wir eine TSecondclass-Instanz erstellt haben, folglich zeigt ClassName auch TSecondclass an, da Classname auf der VMT beruht, die nun mal TSecondclass ist. Wir würden 'TBaseClass' erhalten, wenn wir ein showmessage mit dem hartcodierten Klassennamen in beiden Konstruktoren seperat aufrufen würden.
Probier meinen Vorschlag aus und dann....
Der Zugriff auf den Klassennamen innerhalb eines aufgerufenen Konstrukturs ruft dynamsich immer den Klassennamen auf der zur aktuellen Klasse in der ich mich befinde zugehörig ist.

Wenn also BaseClass.Create() intern SchoMessage(ClassName) aufruft dann zeigt das den Klassennamen der Klasse auch an. Wenn wir in BaseClass nun TSecondClass drinen stehen haben der Konstruktor aber NICHT virtuell deklariert wurde dann wird defakto eben nich TSecondClass.Create() aufgerufen sonder TBaseClass.Create(). das ist auch logisch da der Datentyp der Variablen BaseClass: class of TBaseClass ist.

Lerne was Polymorphie heist und warum man bei virtuellen Methoden/Konstrukoren eben BaseClass.Create() aufrufen kann und der richtige Konstruktor nur dann aufgerufen wird wenn dieser als virtuel deklariert wurde.

Probiere es erstmal aus.

Was bestimmt denn bei einem Object zu welcher Klasse es gehört ? Probiert das aus

Delphi-Quellcode:
type
  PPointer = ^Pointer;
var
  Obj: TObjct;
begin
  Obj := TObject.Create;
  ShowMessage(Obj.ClassName);

  PPointer(Obj)^ := @TComponent;
  
  ShowMessage(Obj.ClassName);
end;

// oder das

type
  TMyClass = class(TObject)
    procedure Test;
  end;

procedure TMyClass.Test;
begin
  ShowMessage(ClassName);
end;

procedure Test;
var
  T: TMyClass;
begin
  T := TMyClass.Create;
  T.Test;

  PPointer(T)^ := @TPanel;

  T.Test;
end;
Gruß hagen
  Mit Zitat antworten Zitat
Sidorion

Registriert seit: 23. Jun 2005
403 Beiträge
 
#18

Re: Konstruktor Create Virtual oder nicht?

  Alt 30. Aug 2007, 08:21
Ähhh verwechselt mal bitte nicht das Schlüsselwort 'static' mit statischen Methoden. 'static' entspricht 'class' vor einer Funktion/Methode in Delphi und bedeutet nur, dass man diese Methode ohne Instanz rufen kann (geht bissi über Class Function hinaus, aber das führt hier zu weit). Insofern können in C++ 'static' Methoden durchaus überschrieben werden (genauso wie class functions). 'static' und 'abstract' hingegen machen wirklich keinen Sinn
Manchmal sehen Dinge, die wie Dinge aussehen wollen mehr wie Dinge aus, als Dinge
<Esmerelda Wetterwachs>
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#19

Re: Konstruktor Create Virtual oder nicht?

  Alt 30. Aug 2007, 08:56
Zitat von Sidorion:
Insofern können in C++ 'static' Methoden durchaus überschrieben werden (genauso wie class functions).
Verdeckt, aber nicht überschrieben. Ausser du deklarierst sie als virtuell...

Nochwas: class procedure die als virtuell und abstract markiert werden, werden in Delphi ordentlich gehandelt (samt Überschreiben etc). Ich hatte dieses Verhalten angewandt um bei meiner XMLLib die StringAdapter zu bauen. Hintergrund: Ich wollte vor anlegen der Instanz wissen, welche Zeichenkodierung die Klasse implementiert. Da ich nur einen Klassenreferenztyp hatte, musste es eine virtuelle Methode sein um den zu bekommen. Da es aber auch noch ohne Instanz vorher aufgerufen werden musste, wurde es zu einer virtuellen class procedure. Nächster Schritt: Jeder der einen solchen StringAdapter baut muss mir mindestens diesen Coding String zurück geben - somit abstract. Dieses Verhalten klappte soweit, bis ich versuchte die Klasse im C++Builder zu übersetzen. Dort wollte der Compiler diesen Konstrukt nicht mehr übersetzen (obwohl es doch noch immer der Delphi Compiler war) - ich vermute da Delphi dort etwas stark eigenes baut, was dann der C++Builder/Compiler nicht mehr nutzen kann, wenn ich von der Klasse mit einem solchen Konstrukt ableiten würde.

Ich habe nun alles ohne Zwang zu überschreiben und das klappt einwandfrei. Also nur das abstract entfernt.
  Mit Zitat antworten Zitat
Sidorion

Registriert seit: 23. Jun 2005
403 Beiträge
 
#20

Re: Konstruktor Create Virtual oder nicht?

  Alt 30. Aug 2007, 09:27
Hmmmm ich hab jetzt doch mal mein Wischelstudio angeschmissen, um mal genau nachzuforschen: static kann nicht zusammen mit Vererbung benutzt werden (kein virtual, override oder abstract). Insofern isses gegenüber Delphi eingeschränkter, allerdings kann ich in C++ auch Variablen static machen, was bei Rekursionen und so extrem lecker sein kann. Hier heisst das dann das diese Variable nur einmal im Programm existiert (allerdings mit den entsprechenden Scopierungen, wie Klasse, Funktion usw.).
[edit]insofern sind 'static' Methoden auch statische Methoden, umgekehrt aber nicht zwingend (da fehlt dann einfach das virtual wie in Delphi)[/edit]
Manchmal sehen Dinge, die wie Dinge aussehen wollen mehr wie Dinge aus, als Dinge
<Esmerelda Wetterwachs>
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


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 16:29 Uhr.
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