![]() |
Zeigerproblem
Hiho,
Ich hab es (noch) nicht so mit Zeigern und daher keine Ahnung was Delphi nun wirklich von mir will.
Delphi-Quellcode:
Schmeißt bei Aufruf in der markierten Zeile den Fehler "Variable erforderlich".
TBarGraph = class
private PBitmap: ^TBitmap; FBars: Array of Integer; procedure Bar(const aPosition, aValue: Integer); procedure ArraySwap(const aPosition1, aPosition2: Integer); procedure BitmapSwap(const aPosition1, aPosition2: Integer); public constructor Create(var aImage: TImage; aForm: TForm); destructor Destroy; override; procedure Draw; procedure BubbleSort; procedure QuickSort(const aLow, aHigh: Integer); end; var Form1: TForm1; bKill: Boolean; MyBarGraph: TBarGraph; implementation {$R *.dfm} constructor TBarGraph.Create(var aImage: TImage; aForm: TForm); const MAXRANDOM= 530; BARQUANTITY= 150; var iCounter: Integer; begin inherited Create; setLength(FBars, BARQUANTITY); for iCounter:= 0 to High(FBars) do FBars[iCounter]:= random(MAXRANDOM)+1; PBitmap:= @aImage.Picture.Bitmap; //<-------- PBitmap^.Height:= MAXRANDOM+20; PBitmap^.Width:= (Length(FBars)*4)+8; aImage.Height:= PBitmap^.Height; aImage.Width:= PBitmap^.Width; aForm.Height:= PBitmap^.Height+130; aForm.Width:= PBitmap^.Width+100; end; Was ist daran falsch? MfG. |
Re: Zeigerproblem
Wozu brauchst du den Zeiger? Schmeiss das ^ bei der Deklaration raus und das @ bei der Zuweisung. Instanzenvariablen sind intern schon Zeiger, somit alles wie gehabt und keine Verrenkungen nötig.
|
Re: Zeigerproblem
Und wenn ich es doch so machen wollte?
Ich will ja was bei lernen. Und dabei mein ich nicht unbedingt wie man es am besten macht. ^^ |
Re: Zeigerproblem
Zitat:
Und zu deinem Problem Bitmap ist eine Property und somit kannst du davon keine Adresse ermitteln. Aus dem einfachen Grund da eine Property mit einem Getter, Setter oder einer direkten Variablenreferenz definiert werden kann. Somit kann er keine Adresse ermitteln. |
Re: Zeigerproblem
Wenn du etwas über die Verwendung von Zeigern lernen möchtest, dann suche dir besser einen anderen Anwendungsfall: Vielleicht eine einfach oder doppelt verkettete Liste, da macht es Sinn und ist auch didaktisch besser (denke ich mir mal so)
|
Re: Zeigerproblem
Nun ich wollte hier Zeiger einsetzen, weil ich mir die Bitmap an Image.Picture als Objekt TBitmap vorgestellt hab, mit dem ich arbeiten will.
Meine Logik sagt mir ich brauch nen Pointer darauf. Aber ich hab es nun so gemacht und es geht. ^^
Delphi-Quellcode:
Danke&MfG^^
PBitmap: TBitmap;
.. PBitmap:= aImage.Picture.Bitmap; |
Re: Zeigerproblem
Zitat:
Zitat:
|
Re: Zeigerproblem
Ok, das heißt, wenn ich es richtig versteh:
Image.Picture.Bitmap ist ein Pointer auf eine Bitmap, also eine Speicheradresse. Dann müsste
Delphi-Quellcode:
ja funktionieren.
var
ptrBitmap: ^TBitmap; begin ptrBitmap:= Image.Picture.Bitmap; end; Es kommt aber inkompatible Typen Pointer und TBitmap. Wird das schon intern dereferenziert und wenn ja gibt es einen Befehl mit dem man es verhindern kann? (Ich wüsste einfach gern ob und wie ich darauf einen eigenen Pointer machen kann.) MfG^^ |
Re: Zeigerproblem
Zitat:
Wir nehmen uns ein Objekt:
Delphi-Quellcode:
Dann hast du dort an der Stelle von a nicht direkt das komplette TObject mit allen seinen Methoden und Feldern sondern nur einen Zeiger. Dieser würde dann auf den Speicherbereich zeigen, wo die Felder, etc liegen. Wenn du diese Variable deklariert hast, kannst du ja mal mit SizeOf(a) deren Grösse ermitteln: du wirst 4 bekommen. 4 Bytes, also genau die Grösse eines Pointers.
var
a: TObject; Du musst, um das Objekt nutzen zu können, die eine Instanz erstellen. Diese erhälst du mit dem Konstruktor-Aufruf. Dieser reserviert den notwendigen Speicher für das Objekt und gibt dir den Zeiger genau auf diesen Speicherbereich zurück. Von daher kannst du es auch abfragen ob ein Objekt existiert, wenn die Variable ordentlich intialisiert wird. Du kannst mit einem Vergleich auf <> nil abprüfen, ob schon eine Adresse drinne steht (wie bei einem Pointer btw). Deshalb haben auch viele Probleme mit den Objekten, wenn sie Free aufrufen und danach weiterhin auf das Objekt zugreifen und AV's bekommen und selbst Assigned() bzw. ein Vergleich auf Nil nichts bringt: Der Zeiger zeigt weiterhin auf die Adresse (hat ihm ja keiner was anderes gesagt), aber da ist nichts mehr. Somit: FreeAndNil() ruft Free auf und setzt den Zeiger auf NIL und somit klappen die Abfragen auch. Anderes Beispiel:
Delphi-Quellcode:
Bei dem Beispiel erzeugst du nur ein Objekt. Wäre a und b jeweils intern kein Zeiger, dann müsste er das komplette Objekt kopieren, da es komplett eigene Speicherbereiche sind. Wenn dem so ist, dann müsste die ShowMessage() einen leeren String ausgeben. Tut er aber nicht, sondern er gibt "erstes Object" aus. Grund dafür: er kopiert nur die Adresse aus dem Pointer in den anderen. Somit zeigen beide auf das selbe Objekt im Speicher.
var
a, b: TStrings; begin a := TStringList.Create; // neue Instanz b := a; // Objekt wird nicht kopiert, nur der Zeiger! a.Text := 'erstes Object'; ShowMessage(b.Text); end; Also: Wenn du eine Objektvariable deklarierst, ist diese nur 4 Bytes gross, da es ein Zeiger ist. Dies ist das interne Handling, somit geschieht auch die Dereferenzierung automatisch intern von Delphi. Und ausserdem ist Delphi recht typensicher (wie oft habe ich das in den letzten Tagen geschrieben...) und TBitmap und Pointer sind nunmal unterschiedliche Typen. |
Re: Zeigerproblem
Nimm zum Üben einen Record bzw einen Pointer auf diesen Record. Objekte sind zum Üben von Pointern denkbar ungeeignet.
|
Re: Zeigerproblem
Für mich, der grad aus der Kneipe kommt und aus lauter Frust ein .. zwei Bier zu viel getrunken hat, weil er nicht ein einzigstes Dartspiel gewonnen hat (man, und ich war mal so gut darin), stellt sich die Frage:
Willst du was über Zeiger lernen, oder des Problem lösen. Für die Lösung hätte ich einen Tipp. Lass das ganze Zeiger-gemurks (^ und @) weg. Dein Parameter aImage ist sowieso ein Zeiger auf das Original-Image, so wie Muetze1 schreibt. Mit dem kannst du genauso weiter arbeiten, als wenn du das Image "direkt in der Form" ansprichst. Das ist nämlich letzten Endes eben auch nur ein Zeiger. Für das, was ich deinem Code entnehmen kann reicht das völlig. Zitat:
Delphi-Quellcode:
... würde reichen. Du kopierst nur den Zeiger. Das ist doch das was du vor hast, oder?
var
oBitmap: TBitmap; begin oBitmap:= Image.Picture.Bitmap; end; Bitte nicht übel nehmen, aber ich glaube, du hast den Begriff "Instanz" nicht richtig vereinnahmt. TImage ist die Klasse. mit
Delphi-Quellcode:
instanzierst du die Klasse.
aImage := TImage.create (??);
aImage ist also eine Instanz der Klasse TImage, was eigentlich nur ein Zeiger ist (siehe Muetze1). Alle Unterobjekte von aImage sind auch nur Instanzen (Zeiger) der entsprechenden Klassen. So sollte es eigentlich funktionieren:
Delphi-Quellcode:
Wenn du Objekte (also alles das, was von TObject erbt) in eine Procedure/Funktion übergibst, übergibst du eigentlich nur den Zeiger auf das Objekt.
constructor TBarGraph.Create(var aImage: TImage; aForm: TForm);
const MAXRANDOM= 530; BARQUANTITY= 150; var iCounter: Integer; begin inherited Create; setLength(FBars, BARQUANTITY); for iCounter:= 0 to High(FBars) do FBars[iCounter]:= random(MAXRANDOM)+1; aImage.Picture.Bitmap.Height:= MAXRANDOM+20; aImage.Picture.Bitmap.Width:= (Length(FBars)*4)+8; aImage.Height:= PaImage.Picture.Bitmap.Height; aImage.Width:= aImage.Picture.Bitmap.Width; aForm.Height:= aImage.Picture.Bitmap.Height+130; aForm.Width:= aImage.Picture.Bitmap.Width+100; end; das ist das gleiche wie zB.
Delphi-Quellcode:
Ich gebe dir mein leeres Bierglas mit, und du kommst mit dem _selbem_ Glas wieder zurück, nur das es jetzt voll ist.
procedure HoleBier (Var aGlas : Integer); // Zeiger auf Variable wird kopiert
begin if aGlas = 0 then aGlas := 100; end; Mit folgender Funktion würdest du mit _meinem_ Glas wieder zurück kommen, es wäre aber weiterhin leer.
Delphi-Quellcode:
Was mit dem Bier passiert ist weiß ich nicht. Es ist halt weg.
procedure HoleBier (aGlas : Integer); // Variable wird kopiert
begin if aGlas = 0 then aGlas := 100; end; Da aber Glas eigentlich ein TObject ist (sein sollte), welches unter anderem das Property Inhalt hat, kommst du mit folgender Funktion:
Delphi-Quellcode:
mit _meinem_ Glas wieder, welches aber wieder voll wäre.type TGlas = Class (TObject); public Property Inhalt : Integer; [...] procedure HoleBier (aGlas : TGlas); // Zeiger auf Object wird kopiert begin if aGlas.Inhalt = 0 then aGlas.Inhalt := 100; end; Mit TImage ist es genau das gleiche. Ich hoffe, ich hab keinen Quatsch erzählt ... :cheers: |
Re: Zeigerproblem
[OT] Warum seid Ihr alle noch online? :) [OT]
|
Re: Zeigerproblem
So, nachdem ich mich durch die vielen Informationen durchgearbeitet hab..
@Muetze1: FreeAndNil() kennt mein Delphi 2005 nicht. @gmc616: Eigentlich dachte ich schon, dass mir klar ist, was eine Instanz ist. Dein Konstruktorvorschlag umgeht das Thema des Threads. oO (Ich brauch die Variable in der Klasse.) @Beide: Das einzige Problem, das ich hatte, war offenbar der Umgang mit Objektvariablen. Mein alter Gedankengang etwas genauer:
Delphi-Quellcode:
Aber dank den guten Erklärungen hab ich es jetzt denk ich richtig verstanden. ^^
var
ptrBitmap: ^TBitmap; begin Image.Picture.Bitmap = 0x12345 //Bsp.Adresse ptrBitmap = null ptrBitmap:= Image.Picture.Bitmap; //null <-überschreibt- 0x12345 Image.Picture.Bitmap = 0x12345 ptrBitmap = 0x12345 end; MfG. |
Re: Zeigerproblem
Zitat:
|
Re: Zeigerproblem
@nEmai: Nochmal TBitmap ist schonn ein Zeiger (Referenz)!!!!!!!!
|
Re: Zeigerproblem
@Muetze1
Delphi-Quellcode:
Das ist alles was mir an dem Bsp. mit free angezeigt wird, bei FreeAndNil Compilierfehler.
var
Bitmap: TBitmap; begin Bitmap:= TBitmap.Create; Bitmap.FreeImage; Bitmap.Free; Bitmap.FreeInstance; end; Zitat:
Zitat:
|
Re: Zeigerproblem
FreeAnNil() ist eine Prozedur und keine Methode:
Delphi-Quellcode:
FreeAndNil( Bitmap);
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz