Forward type not resolved ?

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
pluto
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)

Beitrag von pluto »

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 )
MFG
Michael Springwald

pluto
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)

Beitrag von pluto »

habe das problem wieder und zwar möche ich eine klasse defnieren die weiter unten durch uses eingebunden wird....

ich hoffe das ich auch hier wieder eine andre lösung finde !
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

@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.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
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)

Beitrag von pluto »

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 !
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

@pluto

Verzechis bei den Compiler-Optionen auch dazugenommen?
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
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)

Beitrag von pluto »

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 :(
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

@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.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Pluto komm nicht immer mit solchen aussagen das lässt sich alles recht einfach lösen posten bitte konkrete Sachen im Zweifelsfall den Code aber zumindest abschnitte
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
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)

Beitrag von pluto »

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 ?
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

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:

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.
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.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
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)

Beitrag von pluto »

ja ich glaube ich verstehe jetzt langsamm warum das so nicht geht.. eine lösung habe ich noch nicht gefunden wie ich das umgehen kann(leider) !
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

@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.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
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)

Beitrag von pluto »

naja ich habe das jetzt mit einem ereignis gelöst... es wird dann ausgelöst wo ich den bevel aus der andren klasse brachte.... ist zwar keine schöne lösung aber es geht !
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

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. :lol:
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
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)

Beitrag von pluto »

ja schon, aber ich muss es ja irgenwo defnieren und betnutzen und ich glaube das es in meinen fall schwirkeiten giben wird. !
MFG
Michael Springwald

Antworten