Autor Beitrag
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Di 25.09.07 20:15 
Hi!
Ich bin grad beim Umschreiben einer größeren Klasse auf das klassische Problem gestoßen, dass ich eine überkreuzte Benutzung im Interface Teil produziere (in etwa sowas, wie z.B. hier: www.delphi-forum.de/...hlight=%DCberkreu%2A). Die Änderungen, die ich jetzt an meiner Klasse gemacht habe, kann ich jetzt wieder rückgängig machen, weil eine Ausweichlösung gegenüber der alten Lösung keine wirklichen Vorteile bietet.

Mich würde interessieren, warum es in Delphi nicht möglich ist, einen überkreuzenden Bezug im Interface Teil zu produzieren (nochmal simples Beispiel unten, zur Visualisierung :mrgreen: ). Welchen Grund hat das, ist der historischer oder technischer Art, oder ist das einfach Design?
(ich sehe in dieser Beschränkung) im Moment keinen Vorteil, außer ich übersehe etwas

Hier zum Bleistift:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
interface

type

TClassA = class
variable: TClassB;
end;

TClassB = class
variable: TClassA;
end;


Viele Grüße
alias5000

Moderiert von user profile iconjasocul: Link-Tags gesetzt

_________________
Programmers never die, they just GOSUB without RETURN
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Di 25.09.07 20:19 
Versuchs mal mit einer forward-Deklarartion

_________________
Markus Kinzler.
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Di 25.09.07 22:24 
-- doch net sry

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Di 25.09.07 22:26 
@Tilman: das ist eine forward-(Klassen-)Deklaration

_________________
Markus Kinzler.
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Di 25.09.07 22:34 
Ich war mir momentan nicht sicher ob das überhaupt so richtig war, poste du doch mal wie man's genau macht :-)

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 25.09.07 23:07 
user profile iconalias5000 hat folgendes geschrieben:
Mich würde interessieren, warum es in Delphi nicht möglich ist, einen überkreuzenden Bezug im Interface Teil zu produzieren (nochmal simples Beispiel unten, zur Visualisierung :mrgreen: ).
Das geht natürlich:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
interface

type
TClassB = class;

TClassA = class
variable: TClassB;
end;

TClassB = class
variable: TClassA;
end;
Hintergrund: Delphi muss bei der Verwendung der Klasse TClassB wissen, dass die existiert und daher musst du das vorher angeben. Ergänzen kannst du dann die Klasse später.
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Di 25.09.07 23:31 
Hi,

damals in meiner Ausbildung wurde das auf Turbo Pascal bezogen (mit funktionen und proceduren anstelle von Objekten) damit begründet, dass der Compiler die Datei ansonsten noch ein weiteres mal "vorparsen" müsste. Also erst einmal die ganze unit parsen um alle (globalen)Variablen, Funktionen und Klassen kennen zu können und erst dann das Eigentlich parsing bei welchen diese dann verwendet werden beginnen kann. Es währe also ein nicht unaufwändiger arbeitsschrit mehr und würde damit das Kompilieren langsamer machen. Da es nicht so häufig vorkommt (wenn dann meist bei verketteten Listen und da haben die meisten Leute das deklartionschema eh im Kopf oder im Lehrbuch) spart man sich lieber den Arbeitsschrit und erlaubt dafür die von user profile iconjaenicke gezeigten forward deklarationen.

Gruß
Klabautermann
Reinhard Kern
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 591
Erhaltene Danke: 14



BeitragVerfasst: Mi 26.09.07 09:12 
user profile iconKlabautermann hat folgendes geschrieben:
Hi,

damals in meiner Ausbildung wurde das auf Turbo Pascal bezogen (mit funktionen und proceduren anstelle von Objekten) damit begründet, dass der Compiler die Datei ansonsten noch ein weiteres mal "vorparsen" müsste.
...
Gruß
Klabautermann


Hallo,

ich weiss nicht, wie lange deine Ausbildung her ist, aber die Idee des 1 Pass-Compilers hat sich offenbar in den Köpfen der Borland-Programmierer unwiderruflich festgefressen, obwohl es viele Nachteile gibt: Turbo Pascal war immer bekannt dafür, sehr schnell zu übersetzen, dafür aber beim ersten Fehler abzubrechen. Unter DOS hatte ich als Alternative einen Pascal-3-Pass-Compiler von Prospero, da zeigte sich der Unterschied ganz deutlich: mit TP compilieren, Fehler 1 beheben, compilieren, Fehler 2 beheben usw. Bei Propascal liess ich den Compiler laufen und beseitigte nach den Meldungen die meisten Fehler gleich nach dem ersten Durchlauf. Damit war der Geschwindigkeitsvorteil von TP futsch.

Borland/Codegear hat inzwischen viele Energien daran verschleudert, den Compiler in einem Durchlauf möglichst weit kommen zu lassen, hat aber den Schritt zu mehr als einem Pass gescheut. Das hat leider auch andere gravierende Nachteile, z.B. dass in mehreren Units definierte Konstante und Variablen überhaupt nicht erkannt werden, so dass im Mapfile Publics mehrfach auftauchen - da ist Delphi die einzige mir bekannte Sprache, das kann jeder 2-Pass-Assembler besser.

Damit leiden wir an einem Erbe, das aus den Zeiten der CP/M-Diskettensysteme stammt. Auf heutiger Hardware würde ein 2. Durchlauf überhaupt nicht auffallen.

Gruss Reinhard
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 26.09.07 12:28 
user profile iconReinhard Kern hat folgendes geschrieben:
Unter DOS hatte ich als Alternative einen Pascal-3-Pass-Compiler von Prospero, da zeigte sich der Unterschied ganz deutlich: mit TP compilieren, Fehler 1 beheben, compilieren, Fehler 2 beheben usw. Bei Propascal liess ich den Compiler laufen und beseitigte nach den Meldungen die meisten Fehler gleich nach dem ersten Durchlauf. Damit war der Geschwindigkeitsvorteil von TP futsch.
Soo viele Fehler habe ich eigentlich nie in meinem Quelltext, dass sich das lohnen würde. Normalerweise habe ich vielleicht maximal 3-4 Fehler, wenn ich 500 Zeilen oder so blind programmiert habe. Schließlich werden die meisten Fehler ja auch schon beim Schreiben des Quelltextes markiert.

Vor allem sehe ich nicht, wie man unterscheiden soll zwischen Folgefehlern und tatsächlichen Fehlern, die behoben werden müssen (da weiß ich ja nicht, wie das bei Propascal ging). Klar sieht man die meisten echten Fehler eh gleich, wenn man die Fehlerliste durchgeht, aber es macht finde ich viel mehr Mühe als einfach sequentiell die wenigen Fehler, die man gemacht hat, zu beheben. Bei Delphi werden ja auch noch mehr Fehler nach dem ersten angezeigt, aber ich behebe eh erst den ersten und kompiliere neu, einfach um nicht an Folgefehlern zu rätseln (eben weil da ja eigentlich gar kein Fehler ist).
Und wer noch nicht so lange mit Delphi arbeitet und viele Fehler macht, der wird ohnehin nicht gleich alle Fehler beheben wollen, weil er ja vermutlich erstmal prüfen wird, ob die Korrektur des ersten Fehlers stimmte.

Was die Compilierzeit angeht: Die ist schon jetzt bei einem Projekt 31 Sekunden und bei nem anderen 25 Sekunden (auf nem 5000er X2...), da möchte ich nicht wissen, wie das mit nem Multipass-Compiler wäre...

Insofern sehe ich da gar nicht so viele Vorteile gegenüber einem Singlepass-Compiler, und die nötigen Forward-Deklarationen machen ja auch nicht so viel Mühe.
alias5000 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Mi 26.09.07 19:42 
Hallo!
Ich finde die aktuelle Diskussion bzgl. den Compilern recht interessant.
Das, was Jaenicke vorgeschlagen hat, bezeichnet man als Forward-Deklaration, wenn ich das richtig rausgehört habe?
Vielen herzlichen Dank für diesen Tipp! :)

Ich werde das jetzt mal versuchen so umzusetzen. Ich nehme an, dass sich damit meine Frage erledigt hat.

Gruß
alias5000

_________________
Programmers never die, they just GOSUB without RETURN
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 26.09.07 20:12 
user profile iconReinhard Kern hat folgendes geschrieben:

Borland/Codegear hat inzwischen viele Energien daran verschleudert, den Compiler in einem Durchlauf möglichst weit kommen zu lassen, hat aber den Schritt zu mehr als einem Pass gescheut.

Entschuldige, aber das ist so nicht korrekt. Die Fehler vom 'Compiler' schmeisst der Parser aus, und nicht ein n-Pass Compiler. Die Sprache definiert, ob ein nicht deklarierter Bezeichner bei der Verwendung ein Fehler ist, oder nicht.

Delphi / Objekt Pascal erlaubt einfach per definitionem keine Verwendung von Bezeichnern VOR deren Deklaration. Historisch dürfte das im 1-Pass-Compiler verwurzelt sein, das so ein Programm immer 'häppchenweise' übersetzt wird, um Speicher zu sparen. Es hat auch mit der Typensicherheit und den festen Parameterlisten von Prozeduren zu tun, die z.B. bei C nicht gegeben sind.

Früher wurden mehrere Durchläufe (Pass) benötigt, um den Quellcode zu parsen, zu compilieren und zu optimieren. Heutzutage reicht imho ein Durchlauf aus, um das zu bewerkstelligen. C z.B. war früher ein klassisches 2-Pass-Compiler (1.parsen + Macros übersetzen, 2.Codegenerierung).

Das Wiederaufsetzen des Parsers nach einem Syntaxfehler an der richtigen Stelle ist nicht einfach, und manchmal unmöglich. Aus diesem Grund bricht ein Compiler manchmal einfach ab, eben weil er nicht herausbekommen kann, was logisch als nächstes folgen müsste.
Die einfachsten Compiler in der Steinzeit der Computer brachen beim ersten Syntaxfehler einfach ab. Damals war die Forschung einfach noch nicht so weit. Ich habe jedoch schon Anfang der 80er Jahre mit UCSD-Pascal-Compilern gearbeitet, die eigentlich alle Fehler moniert haben. Insofern ist es wohl kein Verdienst der Codegear/Borland-Typen, den Compiler hier verbessert zu haben. Auch kann ich mich nicht erinnern, das sich Delphi 3 bei Fehlern verschluckt hat. Oder ich hab einfach nicht so viele gemacht, kann auch sein.

_________________
Na denn, dann. Bis dann, denn.