Autor |
Beitrag |
Gewuerzgurke
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Mi 01.07.09 18:17
Hallo, ich suche nach einer Möglichkeit, den Typen eines Pointers zu ändern. Mein Problem: Ich habe zwei verschiedene Records. Jedes Record enhält eine (keine Ahnung, wie es in Records heist) "Variable" Transparency. Zu jedem Record habe ich auch den passenden Pointer. Also:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| type PRec1 = ^TRec1; TRec1 = record Transparency : Cardinal; AndereVariablen : sonstwas; end; PRec2 = ^TRec2; TRec2 = record Transparency : Cardinal; GanzAndereVariablen : irgendwas; end;
var Rec1 : TRec1; Rec2 : TRec2; |
In meiner Funktion möchte ich die "Variable" Transparency über einen Poiner erreichen. Wenn ich den Pointer einrichte als PRec1 (also var DerPointer : PRec1;) dann kann ich damit die Variable in Rec2 nicht erreichen (außer Tranzparency steht - wie im Beispiel - in beiden Records an der selben Position, was ich aber in meinem Programm aus verschiedenen Gründen nicht verwirklichen kann...). Ich möchte wissen, ob man den Pointer zur Laufzeit von PRec1 in PRec2 ändern kann - oder ob es eine andere Lösung gibt.
Danke schonmal.
|
|
Boldar
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mi 01.07.09 18:27
Schreib dir doch die Records wie folgt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| type PRec1 = ^TRec1; TRec1 = record function gettransparency: Pointer; Transparency : Cardinal; AndereVariablen : sonstwas; end; PRec2 = ^TRec2; TRec2 = record function gettransparency: pointer; Transparency : Cardinal; GanzAndereVariablen : irgendwas; end;
var Rec1 : TRec1; Rec2 : TRec2;
... function TRec1.gettransparency: pointer; begin result := addr(Transparency); end;
function TRec2.gettransparencypointer: pointer; begin result := addr(Transparency); end; |
Die getter-Funktionen schreibst du dann an die selbe Stelle und ruftst den Wert Dann darüber ab.
Oder es geht villeicht auch mit einem explizitem Typecast, denn du weisst doch, welcher Record das ist?
mfg Boldar
|
|
Narses
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 01.07.09 18:30
Moin!
Wozu gibt´s OOP?! Ich würde da eine(n Satz) Klasse(n) draus machen. Das Pointer-Gehake ist doch eher unschön...
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Gewuerzgurke
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Mi 01.07.09 18:57
Ja, ich habe auch immer versucht, Pointer zu vermeiden, aber dieses Mal geht es nicht anders... außer ich mache riesige "IF-Tabellen". OK, ich könnte auf die Variante mit "function gettransparency: Pointer;" zurückgreifen, aber das währe auch ziemlich aufwändig, wegen den Klassen. Ich hatte gehofft, dass es eine Möglichkeit gibt, nach dem Motto "Wenn Ziel_Von_Pointer = Rec2, dann Position_Von_Transparency = 1", was genau dem Problem mit dem ändern des Typen gleichkäme. Aber es muss doch eine Möglichkeit geben, die Variablen-Adressen abhängig von dem Typ des Records zu bekommen...
|
|
Boldar
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mi 01.07.09 19:02
Meine oben genannte Methode arbeitet nicht mit Klassen, man muss es nicht uf Klassen umstellen, es muss nur eine Methode hinzugefügt werden.
|
|
Narses
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 01.07.09 19:03
Moin!
Gewuerzgurke hat folgendes geschrieben : | Ja, ich habe auch immer versucht, Pointer zu vermeiden, aber dieses Mal geht es nicht anders... außer ich mache riesige "IF-Tabellen". OK, ich könnte auf die Variante mit "function gettransparency: Pointer;" zurückgreifen, aber das währe auch ziemlich aufwändig, wegen den Klassen. |
Du kannst die records auch kaskadieren:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| type TDataRec1 = record end;
TDataRec2 = record end;
TCompositeRec1 = record Transparency: Cardinal; DataRec1: TDataRec1; end;
TCompositeRec2 = record Transparency: Cardinal; DataRec2: TDataRec2; end; | Dann kannst du aber auch gleich eine Klasse nehmen, das ist definitiv besser.
Vielleicht erklärst du mal kurz, was das werden soll, gibt ja vielleicht eine optimalere Alternative.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
jaenicke
Beiträge: 19273
Erhaltene Danke: 1740
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 01.07.09 19:09
Mir kämen da noch variante Records in den Sinn. www.delphi-treff.de/...komplexe-datentypen/ hat folgendes geschrieben: | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type person = record name: string; case erwachsen: boolean of true: (personalausweisnr: integer); false: (kinderausweisnr: integer; erziehungsberechtigte: string); end; | |
Ich nehme aber auch an, dass es eine bessere Lösung gibt...
|
|
Gewuerzgurke
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Mi 01.07.09 19:41
Also was ich machen möchte ist eine Animation (DirectX) mit verschiedenen Objekten. Es giebt verschiedene Sorten von Objekten. Für jede Sorte Objekt ist ein Array da, indem die Objekte "stehen" (Also var Sorte1 : Array of TSorte1;). Um ein Objekt zu verändern, z.B. ausblenden, giebt es eine procedure, die den Wert Transparency verändert. So ziemlich alle Objekte haben das Attribut Transparency, weswegen der Effekt Ausblenden auch auf alle Objekte anwendbar wäre. Aber dafür muss unterschieden werden, zu welcher Sorte das Objekt gehört. Mit einem Pointer könnte ich es mir ersparen, da große "IF-Tabellen" anzulegen. Aber dann habe ich das Problem mit dem Typen des Pointers. Ich glaube irgendwo gelesenzuhaben, dass man diesen Typen ändern kann, aber ganz so einfach ist es wohl nicht...
In diesem Fall würde es wirklich Sinn machen, darauf zu achten, dass Transparency immer an der selben Position im Record steht, aber das währe nicht so "sauber" - oder?
|
|
jaenicke
Beiträge: 19273
Erhaltene Danke: 1740
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 01.07.09 20:11
Du kannst die Pointer auch casten. Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var a: TRec1; b: PRec1; begin b := @a; PRec2(b).Transparency ... | Oder du kannst auch direkt die Speicherstelle benutzen. Allerdings solltest du dann einen packed record nehmen, damit die Variablen direkt hintereinander im Speicher liegen.
|
|
Boldar
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mi 01.07.09 22:20
Für sowas kann man doch sehr gut Klassen nehmen, die sich dann selbst verwalten und evtl. selber zeichnen.
|
|
jaenicke
Beiträge: 19273
Erhaltene Danke: 1740
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 01.07.09 22:23
Ja, sicher, sinnvoller wäre das mit Klassen wohl, wurde ja auch schon gesagt.
Insbesondere, weil man dann allgemeine Sachen in Elternklassen legen könnte und ggf. auch noch mit Interfaces arbeiten könnte. So könnte man das dann alles gleichzeitig erschlagen.
|
|
Reinhard Kern
Beiträge: 591
Erhaltene Danke: 14
|
Verfasst: Mi 01.07.09 23:54
Gewuerzgurke hat folgendes geschrieben : | Hallo, ich suche nach einer Möglichkeit, den Typen eines Pointers zu ändern.
....
|
Warum eigentlich, nimm doch einen Pointer direkt auf Transparency (eine Zuweisung an den Pointer brauchst du ja so oder so):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| type PTransparency = PCardinal; PRec1 = ^TRec1; TRec1 = record Transparency : Cardinal; AndereVariablen : sonstwas; end; PRec2 = ^TRec2; TRec2 = record Transparency : Cardinal; GanzAndereVariablen : irgendwas; end;
var PTrans : PTransparency; Rec1 : TRec1; Rec2 : TRec2;
begin PTrans := @Rec1.Transparency; PTrans := @Rec2.Transparency; |
getestet hab ich das NICHT!
Gruss Reinhard
|
|
jaenicke
Beiträge: 19273
Erhaltene Danke: 1740
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 01.07.09 23:59
Ja, das geht schon so denke ich. Man kann auch noch viel mehr Pointerspielerei hineinbringen. Z.B. um von einem allgemeinen Pointer auf einen der Records auszugehen kann man den auch auf PCardinal casten um auf den Cardinalwert am Anfang zuzugreifen.
SizeOf(Cardinal) = 4 Bytes später kommt dann die nächste Variable, ...
Aber das macht das alles natürlich nicht übersichtlicher.
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 02.07.09 08:11
Je nachdem, wieviele verschiedene Möglichkeiten es gibt, kann entweder die Variante mit dem Varianten Record ODER die Lösung über entsprechende Klassen übersichtlicher sein.
Keinesfalls sollte man aber unnötig Pointer-Casting betreiben, da das die Sache nicht übersichtlicher macht und eher Fehler provoziert.
Insgesamt wäre es aber durchaus mal sinnvoll, noch etwas mehr Quelltext zu bekommen, wie mit der Transparenz gearbeitet werden soll, da das so eher Spekulation ist ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Gewuerzgurke
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Do 02.07.09 15:41
@Reinhard Kern ( <-- Ist jetzt kein Pointer ) - Hab' ich versucht - geht nicht. Es kommt zwar kein Fehler, aber es passiert auch nichts. Schade, denn das währe echt einfach gewesen.
Wenn ich den Pointer (Wie von jaenicke vorgeschlagen) caste (als PCardinal), dann funktioniert es zumindest dann, wenn Transparency als erstes im Record steht. Gibt es eine Möglichkeit, das Ganze nach hinten zu verschieben, soll heißen die Variablen, die vor Transparency kommen wieder "herauscasten"? Ich denk' mal, dafür muss ich dann packed record verwenden.
Wehe, wenn ich dann nochmal das Reckord verändere, aber ich gehe nicht davon aus, dass dies nötig sein wird.
|
|
jaenicke
Beiträge: 19273
Erhaltene Danke: 1740
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 02.07.09 15:58
|
|
Gewuerzgurke
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Do 02.07.09 16:32
Oh, nett, dass du es noch ausprobiert hast. Da muss ich wohl irgendwo einen Fehler gemacht haben. Ich probiere nochmal 'rum.
|
|
Gewuerzgurke
Beiträge: 152
Win XP
Lazarus
|
Verfasst: So 05.07.09 19:24
So, geht!
Mein Fehler war, dass ich versehendlich den Pointer, bevor dieser verwendet wird, nocheinmal zugewiesen habe ( PTrans := @Rec1;). Da kann man vorher soviel richtig machen, wie man will ...sowas blödes aber auch.
|
|
|