Forward type not resolved ?
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
danke, das währe nett... aber ich bin erstaunt darüber das ich immer erst auf dieses problem stoße ich poste dann eine entsprechnde frage und später merke ich oh das kann ich anders regeln... was mehr sinn ergeben würde !
aber ich bin mir sicher unter delphi war das so... obwohl ich bis jetzt sowas nur einmal anwenden musste vor einigen jahren(glaube ich war das )
aber ich bin mir sicher unter delphi war das so... obwohl ich bis jetzt sowas nur einmal anwenden musste vor einigen jahren(glaube ich war das )
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
@pluto
Grundsätzlich Klassen immer in eigenen Units deklarieren. Wenn da zusätzliche Klassen gebraucht werden, dann mit in diese Unit. Dann kann man das mit dem forward machen wenn das nötig ist.
Beispiel, 1 eigenes Formularobjekt mit einem spezialisiertem Listenobjekt. Das kannst Du dann in einer anderen Unit im Implementation-Abschnitt per uses einbinden und das Formular erst dort benutzen.
Grundsätzlich Klassen immer in eigenen Units deklarieren. Wenn da zusätzliche Klassen gebraucht werden, dann mit in diese Unit. Dann kann man das mit dem forward machen wenn das nötig ist.
Beispiel, 1 eigenes Formularobjekt mit einem spezialisiertem Listenobjekt. Das kannst Du dann in einer anderen Unit im Implementation-Abschnitt per uses einbinden und das Formular erst dort benutzen.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
ich habe die klasse extra in eine extra unit gepackt aber es geht immer noch nicht !
ich verstehe das nicht mehr.... warum ist der complier nicht in der lage sowas zu complieren... warum nur !
ich glaube jetzt gibt es keinen anderen ausweg mehr als dieses problem ein für alle mal zu lösen !
ich verstehe das nicht mehr.... warum ist der complier nicht in der lage sowas zu complieren... warum nur !
ich glaube jetzt gibt es keinen anderen ausweg mehr als dieses problem ein für alle mal zu lösen !
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
ja ist es..
ich habe mal bei der DP geschaut und das hier gefunden leider läst es sich nicht bei mir anwenden:
http://www.delphipraxis.net/topic97147. ... d&start=15" onclick="window.open(this.href);return false;
edit:
ich habe gelesen das object pascal keine forword über verschiedne units zuläst !
das wird das problem sein.... aber ich weß trozdem keine lösung
ich habe mal bei der DP geschaut und das hier gefunden leider läst es sich nicht bei mir anwenden:
http://www.delphipraxis.net/topic97147. ... d&start=15" onclick="window.open(this.href);return false;
edit:
ich habe gelesen das object pascal keine forword über verschiedne units zuläst !
das wird das problem sein.... aber ich weß trozdem keine lösung

MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
@pluto
Die forward-Deklaration geht nur in der gleichen Unit. Ist bei Delphi meine ich genauso. Das heißt ja nur, das oben bei type
TMyClass = class;
Dann eine andere Klasse beschreibst:
TMyForm = class(TForm)
private
FMyClass : TMyClass;
end;
und jetzt erst TMyClass tatsächlich deklarierst:
TMyClass = class(TIrgendws)
end;
Jetzt kannst du diese Unit im interface oder im implementation bei uses benutzen. Wenn du TMyClass in einer Klasse der anderen Unit verwenden willst, dann eben im interface.
Du willst aber das Objekt aus Unit1 in Unit2 verwenden und in Unit2 das Objekt aus Unit1. Das geht mit einem forward auf keinen Fall. Das gibt eine zirkuläre Referenz. Das geht immer schief.
In diesem Fall deklariert beide Objekte in einer Unit und kann dann das forward benutzen, dann geht das auch nicht schief.
Die forward-Deklaration geht nur in der gleichen Unit. Ist bei Delphi meine ich genauso. Das heißt ja nur, das oben bei type
TMyClass = class;
Dann eine andere Klasse beschreibst:
TMyForm = class(TForm)
private
FMyClass : TMyClass;
end;
und jetzt erst TMyClass tatsächlich deklarierst:
TMyClass = class(TIrgendws)
end;
Jetzt kannst du diese Unit im interface oder im implementation bei uses benutzen. Wenn du TMyClass in einer Klasse der anderen Unit verwenden willst, dann eben im interface.
Du willst aber das Objekt aus Unit1 in Unit2 verwenden und in Unit2 das Objekt aus Unit1. Das geht mit einem forward auf keinen Fall. Das gibt eine zirkuläre Referenz. Das geht immer schief.
In diesem Fall deklariert beide Objekte in einer Unit und kann dann das forward benutzen, dann geht das auch nicht schief.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
das mit dem zirkuläre Referenz habe ich nie verstanden warum das nicht geht !
ich dachte ich hätte da eine idee und zwar ich ändere die reinfolge der klassen defination aber das geht leider auch nicht !
in meinem fall ist aber leider die klasse auf die ich zugreifen möchte in einer andren unit definiert !
das mit dem interface habe ich noch nicht ganz verstanden... wie läst sich diesr auf mein problem anwenden ?
@Christian
was meinst du mit deiner aussage ?
ich dachte ich hätte da eine idee und zwar ich ändere die reinfolge der klassen defination aber das geht leider auch nicht !
in meinem fall ist aber leider die klasse auf die ich zugreifen möchte in einer andren unit definiert !
das mit dem interface habe ich noch nicht ganz verstanden... wie läst sich diesr auf mein problem anwenden ?
@Christian
was meinst du mit deiner aussage ?
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
Na, ist doch eigentlich ganz einfach, findet der Compiler im uses des interface-Abschnittes eine unit so versucht er die zu laden und zu kompilieren undzwar bevor er die Unit parst in der er den Verweis findet. Zu diesem Zeitpunkt hat er aber noch keine Kenntnis von den Deklarationen der aufrufenden Unit, also kann er auch dessen Klassen nicht kennen.
Wenn nun aber eine Klasse aus der aufrufenden Unit in der geparsten Unit verwendet wird, so kann er über die Existenz der Klasse nichts wissen und gibt einen Fehler aus. Das kann auch ein forward in der anderen Unit nicht verhindern, da nach dem parsen die Deklaration ja immernoch nicht existiert.
Setzt Du nun in der uses der aufgerufenen Unit im interface-Abschnitt die aufrufenden Unit ein, das würde dann so aussehen:
Dann führt das beim Compiler zu einer Deadlock-Situation. Aus Unit1 heraus versucht er Unit2 zu parsen, bevor er damit loslegen kann wird aber Unit1 angefordert und er muß zu Unit1 wechseln, dort wird er wieder in Unit2 geschickt.
Er dreht sich also im Kreis und kommt niemals zum Ende. Das gilt auch, wenn die Anforderung im implementation-Abschnitt steht. Für den Compiler ist eine Klasse erst dann vorhanden, wenn er sie vollständig geparst hat.
Das meint man mit zirkulärer Referenz.
Wenn nun aber eine Klasse aus der aufrufenden Unit in der geparsten Unit verwendet wird, so kann er über die Existenz der Klasse nichts wissen und gibt einen Fehler aus. Das kann auch ein forward in der anderen Unit nicht verhindern, da nach dem parsen die Deklaration ja immernoch nicht existiert.
Setzt Du nun in der uses der aufgerufenen Unit im interface-Abschnitt die aufrufenden Unit ein, das würde dann so aussehen:
Code: Alles auswählen
// hier die erste Unit
unit Unit1;
interface
uses
Unit2; // hier wird Unit2 angefordert
type
implementation
end.
// jetzt Unit2
unit Unit2;
interface
uses
Unit1; // hier wird Unit1 angefordert
type
implementation
end.
Er dreht sich also im Kreis und kommt niemals zum Ende. Das gilt auch, wenn die Anforderung im implementation-Abschnitt steht. Für den Compiler ist eine Klasse erst dann vorhanden, wenn er sie vollständig geparst hat.
Das meint man mit zirkulärer Referenz.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
@pluto
Im Dreieck bauen. Dann ist sind in einer Unit die beiden anderen sicher bekannt. Anstatt dann direkt die Klasse in der jeweiligen Unit zu verwenden, setzt man einfach eine Eigenschaft auf:
FMyObjekt: TObject;
Zu einem solchen Objekt sind aller Objekte zuweisbar die in irgendeiner Form von TObject abstammen, also fast alle.
Dann benutzt man in den beiden Objekten eine Event um die nötigen Daten zu übergeben. Dann darf man im Eventhandler:
TMyClass(Sender)^.
die Klasse refenzieren. Ist zwar etwas umständlich aber das geht deshalb, weil man es jetzt nur mit einem Zeiger auf ein Objekt zu tun hat. Ein Zeiger kann aber grundsätzlich alles aufnehmen, ist ja lediglich eine Adresse im Speicher. In diesem Fall die Adresse des jeweils anderen Objekts.
Braucht man kein forward und die beiden Klassen brauchen nichts voneinander wissen. Etwas Hirnschmalz ist allerdings gefordert. Bevor man so refenziert muß auch klar sein welchen Typ Sender hat.
Im Dreieck bauen. Dann ist sind in einer Unit die beiden anderen sicher bekannt. Anstatt dann direkt die Klasse in der jeweiligen Unit zu verwenden, setzt man einfach eine Eigenschaft auf:
FMyObjekt: TObject;
Zu einem solchen Objekt sind aller Objekte zuweisbar die in irgendeiner Form von TObject abstammen, also fast alle.
Dann benutzt man in den beiden Objekten eine Event um die nötigen Daten zu übergeben. Dann darf man im Eventhandler:
TMyClass(Sender)^.
die Klasse refenzieren. Ist zwar etwas umständlich aber das geht deshalb, weil man es jetzt nur mit einem Zeiger auf ein Objekt zu tun hat. Ein Zeiger kann aber grundsätzlich alles aufnehmen, ist ja lediglich eine Adresse im Speicher. In diesem Fall die Adresse des jeweils anderen Objekts.
Braucht man kein forward und die beiden Klassen brauchen nichts voneinander wissen. Etwas Hirnschmalz ist allerdings gefordert. Bevor man so refenziert muß auch klar sein welchen Typ Sender hat.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
Man soll es ja nicht glauben aber nicht immer sind die neuesten Methoden die Besten. Eine Datenübergabe der Form:
procedure TMyClass.SomeEvent(Sender: TObject; Data: pointer);
oder:
procedure TMyClass.SomeEvent(Sender: TObject; var Data);
hilft manchmal auch weiter.
procedure TMyClass.SomeEvent(Sender: TObject; Data: pointer);
oder:
procedure TMyClass.SomeEvent(Sender: TObject; var Data);
hilft manchmal auch weiter.

Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)