Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Pointer mit Hütchen (^)... Ich steh auf dem Schlauch
matze - So 22.06.08 13:01
Titel: Pointer mit Hütchen (^)... Ich steh auf dem Schlauch
Hallo Leute,
Auf die Gefahr hin, mich hier als völliger Noobie zu outen...
Ich habe mir letztens mal wieder ein Entwickler-Magazin vorgenommen, das ich noch nicht ganz zu Ende gelesen hatte und bin da auch einen Artikel gestoßen, der den VirtualStringTree beschreibt.
So: Nun gibt man ja bei dieser Komponente nur Objekte in einen Listeneintrag hinein und muss sich dann selber darum kümmern.
Der Autor arbeitet dabei immer recht gerne mit dem ^-Befehl und ich weiß persönlich fast nix darüber...
Wieso muss ich denn, wenn ich mein Objekt wieder aus dem Listitem hole mit TObject(sender.GetNodeData)^); arbeiten? Und wieso muss ich erst mit ^ arbeiten? Wieso kann ich nicht gleich casten?
Gibts denn irgendwo Literatur darüber, wann ich mit dem ^-Operator arbeiten muss und was er macht?
MfG
Matze
Silas - So 22.06.08 13:16
Ein ^ hinter einer Zeigervariable dereferenziert den Zeiger und gibt dir das Objekt zurück, auf das er zeigt, ein @ vor einer Variable macht genau das umgekehrte. Eine Zeile a la type PInteger = ^Integer schließlich definiert einen neuen Zeigertyp, hier einen Zeiger auf einen Integer.
In deinem Fall sieht der Code etwas eigenartig aus, du hast da eine schließende Klammer zuviel :gruebel:. Welche von den beiden ist das?
Ich könnte mir vorstellen, dass hier mit einem Zeiger auf TObject gearbeitet wird, was eigentlich unnötig ist, da ein TObject selbst ein Zeiger ist. Wenn wirklich das TObject dereferenziert wird, dann würde mich das schon etwas wundern... Was für ein Objekt gibt denn Sender.GetNodeData zurück?
Wäre gut, wenn du ein paar Codezeilen drumrum posten könntest.
Yogu - So 22.06.08 13:57
Silas hat folgendes geschrieben: |
Was für ein Objekt gibt denn Sender.GetNodeData zurück? |
Da kommt ein einfacher Zeiger raus. Allerdings sollte dieser auf einen Record verweißen, das ist viel leichter zu verwalten. Den Record musst du dann dereferenzieren, und schon kannst du auf die Klasse zugreifen, die in dem Record definiert wurde. Klingt ein wenig kompliziert, ich hab diese Arbeitsweise aus einem Tutorial von Virtual Treeviews. Weil ich die URL nicht mehr weiß, hänge ich es mal als Anhang an.
Grüße,
Yogu
matze - Mo 23.06.08 09:55
Da hab ich ja erstmal was zum lesen.. :-) Vielen Dank fürs Erste!
Lossy eX - Mo 23.06.08 10:06
Titel: Re: Pointer mit Hütchen (^)... Ich steh auf dem Schlauch
matze hat folgendes geschrieben: |
Wieso muss ich denn, wenn ich mein Objekt wieder aus dem Listitem hole mit TObject(sender.GetNodeData)^); arbeiten? Und wieso muss ich erst mit ^ arbeiten? Wieso kann ich nicht gleich casten? |
Der VirtualTree erstellt intern selbst den an einem Node hängenden Datenbereich. Und mit
GetNodeData bekommt man den Pointer auf diesen Datenbereich zurück. Den muss man Derefenzieren um an den Inhalt zu kommen. Und der besteht in dem Beispiel lediglich aus einem TObject. Bei einer TList reicht man selber einen Pointer rein und bekommt diesen auch direkt wieder raus. Das geht bei der VirtualTree eigentlich auch. Hat bei mir aber irgendwie immer Probleme gemacht. Womöglich bin ich auch zu doof dafür. ;)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| type PBlah = ^TBlah; TBlah = record obj: TObject; end;
var Blah: PBlah; begin Blah := Tree.GetNodeData(Node); Blah^.Obj.Irgendwas; end; |
Das wäre vermutlich weniger verwirrendes Beispiel gewesen. Nur er hat scheinbar direkt einen Pointer auf das Objekt benutzt.
alzaimar - Mo 23.06.08 10:28
Titel: Re: Pointer mit Hütchen (^)... Ich steh auf dem Schlauch
Lossy eX hat folgendes geschrieben: |
Den muss man derefenzieren |
Muss man nicht, Delphi ist so schlau und fügt ein '^' ein, falls man es vergessen hat.
Delphi-Quelltext
1: 2:
| P.Foo := Bar; P^.Foo := Bar; |
Beide Zeilen sind äquivalent. Aus dem gleichen Grund muss man auch keine Objekte dereferenzieren, obwohl eine Objektvariable genaugenommen ja ein Zeiger ist.
Ob man nun das Dach (Caret) nimmt, oder nicht, ist Geschmackssache. Ich würde es nehmen, schon alleine deshalb, um den konzeptionellen Unterschied zu einem Objekt und Record zu veranschaulichen.
Lossy eX - Mo 23.06.08 11:17
... okay. Dann lass mich, für die ganz genauen, meine Aussage korrigieren! Den muss man nicht immer benutzen aber den sollte man grundsätzlich immer benutzen, wenn es sich um einen Pointer auf ein Record handelt. Alleine schon aus Verständlichkeit am eigenen Code.
Motzi - Mo 23.06.08 12:10
Titel: Re: Pointer mit Hütchen (^)... Ich steh auf dem Schlauch
alzaimar hat folgendes geschrieben: |
Aus dem gleichen Grund muss man auch keine Objekte dereferenzieren, obwohl eine Objektvariable genaugenommen ja ein Zeiger ist. |
Wenn du es schon so genau nimmst ;) - nein, das ist nicht der Grund warum man keine Objekte dereferenziert. Objekte sind zwar Referenzen, aber diese werden
immer implizit dereferenziert. Du darfst normale Objektreferenzen gar nicht dereferenzieren. Dasselbe gilt auch für Interfaces, Metaklassen, dyn. Arrays und Strings. All diese Typen sind intern eigentlich nur Zeiger, nur kapselt Delphi deren Funktionalität vollkommen transparent.
Gruß, Motzi
alzaimar - Mo 23.06.08 12:13
Jupp.
Delphi-Quelltext
1:
| MyPost := StringReplace(MyPost,'Aus dem gleichen Grund muss','Aus dem gleichen Grund kann',[]); |
matze - Mo 23.06.08 20:09
Also kann ich den Zeiger, der aus dem VST rauskommt auch direkt auf TObject oder was auch immer casten ohne, dass ich das Caret verwende..?
(Das ist jetzt also so die Quintessenz, die ich aus dem ganze hier rausziehe.
Mir geht es jetzt nicht darum, dass ich mich von dem ^ drücken möchte, aber das sind so Dinge, die man gerne mal vergisst und ich finds auch optisch schöner, wenn man es weglassen kann :zwinker:
Tilman - Di 24.06.08 03:00
Ich hab jetzt keinen Plan von diesen Virtual String Trees, aber grundsätzlich gilt das Object-Instanzen von Delphi selbst dereferenziert werden (So als wäre der Objectzeiger das Objekt selbst), während man die untypisierten und typisierten Pointer selber dereferenziert. Mir schein getNodeDate ist vom Typ Pointer und muss folglich dereferenziert (und gecastet) werden.
Tipp zum lernen: man kann mit Zeigern tolle Listen und Binärbäume programmieren, da kann man prima üben mit. Also einfach einen Record definieren und ab geht die Post.
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: 31: 32: 33: 34: 35: 36: 37:
| type pListItem = ^tListitem; tListItem = record Inhalt: String; NextItem: pListItem; end;
var anker: plistItem = nil;
procedure rein(var pli: pListItem; str: String); begin if pli = nil then begin new(pli); pli^.NextItem := nil; pli^.Inhalt := str; end else rein(pli^.NextItem,str); end;
procedure Zeigen(pli: pListItem); begin if pli <> nil then begin ShowMessage(pli^.Inhalt); Zeigen(pli^.NextItem); end; end;
procedure TForm1.Button1Click(Sender: TObject); begin rein(anker,edit1.text); end;
procedure TForm1.Button2Click(Sender: TObject); begin Zeigen(anker); end; |
// edit
ach ja und heißer Tipp: mir hat es immer geholfen das ^ als "wo er hinzeigt" zu lesen wenn es nach einer Variablen kommt, bzw. als "Zeiger auf" wenn es vor einer solchen steht.
type pZeiger = ^Integer; lese ich also als pZeiger ist ein Zeiger auf Integer.
Zeiger^ = 8; lese ich als: Zeiger, wo er hinzeigt, wird 8.
zeiger = 8; ist folglich: Zeiger wird 8. (Zeiger = Adresse).
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!