Autor Beitrag
matze
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: So 22.06.08 13:01 
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

_________________
In the beginning was the word.
And the word was content-type: text/plain.
Silas
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 478

Windows XP Home
Delphi 2005, RAD Studio 2007, MASM32, FASM, SharpDevelop 3.0
BeitragVerfasst: 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.

_________________
Religionskriege sind nur Streitigkeiten darüber, wer den cooleren imaginären Freund hat ;-)
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: So 22.06.08 13:57 
user profile iconSilas 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
Einloggen, um Attachments anzusehen!
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: So 22.06.08 17:00 
Zum Thema Pointer empfehle ich mein Tutorial auf www.manuel-poeter.de ;)

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
matze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: Mo 23.06.08 09:55 
Da hab ich ja erstmal was zum lesen.. :-) Vielen Dank fürs Erste!

_________________
In the beginning was the word.
And the word was content-type: text/plain.
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Mo 23.06.08 10:06 
user profile iconmatze 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. ;)

ausblenden 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.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mo 23.06.08 10:28 
user profile iconLossy 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.
ausblenden 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.

_________________
Na denn, dann. Bis dann, denn.
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: 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.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mo 23.06.08 12:10 
user profile iconalzaimar 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

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mo 23.06.08 12:13 
Jupp.
ausblenden Delphi-Quelltext
1:
MyPost := StringReplace(MyPost,'Aus dem gleichen Grund muss','Aus dem gleichen Grund kann',[]);					

_________________
Na denn, dann. Bis dann, denn.
matze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: 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:

_________________
In the beginning was the word.
And the word was content-type: text/plain.
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: 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.

ausblenden volle Höhe 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).

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)