![]() |
Delphi-Version: 2007
Zeiger auf eine Klasse
Hallo, ich schreibe ein Programm zum Speichern von Geometrien diverser Motoren.
Die Koordinaten um die Geometrie eines Motors zu beschrieben sollen mit der Klasse TPoints gespeichert werden. TPoints besteht aus einem zweidimensionalen dyn. Array mit X-Y-Koordinaten. Im Programm gibt es später mehrere Instanzen von TPoints, weshalb ich mit Zeigern arbeiten wollte, um auf die gespeicherten X-Y-Koordinaten zuzugreifen. Zu diesem Zweck habe ich einen Zeiger "Ptr:^TPoints" der auf die jeweilige Instanz von TPoints zeigen soll. Leider funktioniert es überhaupt nicht :|
Delphi-Quellcode:
//...
type TCoord_XY = record //Speichert eine X-Y-Koordinate x,y:Double; end; type TPoints = Array of Array of TCoord_XY; //Enthält eine Geometrie aus X-Y-Koordinaten //... procedure TForm1.FormCreate(Sender: TObject); var PointsRotor: TPoints; Ptr:^TPoints; begin SetLength(PointsRotor,2,3); //Setze Größe des Arrays direkt Ptr:=@PointsRotor; SetLength(Ptr,2,3); //Setze die Größe des Arrays über Pointer... Compiler Fehler end; |
AW: Zeiger auf eine Klasse
Ein Record/Array ist keine Klasse.
Erzeuge dir besser einen Pointertyp
Delphi-Quellcode:
type
PPoints = ^TPoints; TPoints = Array of Array of TCoord_XY; //Enthält eine Geometrie aus X-Y-Koordinaten |
AW: Zeiger auf eine Klasse
Ein Pointer auf dynamische Arrays ist keine gute Idee, denn das dynamische Array ist selbst schon ein Pointer.
Lass den Pointer einfach weg – du kannst auch mehrere Variablen haben, die auf dasselbe Array verweisen. Bei Zuweisungen wird nur der Pointer kopiert, nicht das Array. Falls du doch mal ein dynamisches Array kopieren willst, musst du ![]() |
AW: Zeiger auf eine Klasse
Danke für eure Hilfe.
Ich habe jetzt mehrere Varianten probiert und habe festgestellt, dass ich in obigen Beispiel nur einen Syntaxfehler hatte :oops: @NamenLozer: Nach deiner Meinung sollte ich Variante 3 nehmen (siehe Code), oder? In Bezug auf die Performance ist diese Variante doch schlecht, weil das komplette Array nochmals kopiert werden muss.:?: Edit: Variante 1 und 2 hingegen verändern direkt den Inhalt von "PointsRotor" ohne zusätzlichen kopiervorgang.
Delphi-Quellcode:
//....
type TCoord_XY = record x,y:Double; end; type TPoints = Array of Array of TCoord_XY; PPoints = ^TPoints; var Form1: TForm1; //.... procedure TForm1.FormCreate(Sender: TObject); var PointsRotor: TPoints; Ptr:PPoints; Ptr2:^TPoints; Ptr3:TPoints; begin SetLength(PointsRotor, 1,1); //Setze Größe des Arrays direkt PointsRotor[0,0].x:=1; //Schreibe was in das Array... //Variante 1 Ptr:=@PointsRotor; SetLength(Ptr^, 2,1); //Variante 2 Ptr2:=@PointsRotor; SetLength(Ptr2^,3,1); //Variante 3 Ptr3:=PointsRotor; SetLength(Ptr3,4,1); PointsRotor:=Copy(Ptr3,Low(Ptr3),High(Ptr3)+1); end; |
AW: Zeiger auf eine Klasse
Zur Info: Als Delphi von Anders aufgesetzt wurde, wählte er das "Zeigerlose Konzept". Deswegen brauchst Du auch keine Zeiger. Aber Du arbeitest ständig damit.
|
AW: Zeiger auf eine Klasse
Klassen sind Referenzen ( intern auch Zeiger) und Erleichtern den Umgang, da sie das Referenzieren/Dereferenzieren transparent durchführen ( geht z.T. auch bei Zeigertypen). Delphi ist aber trotzdem nicht zeigerlos, da das nur für Klassen gilt.
|
AW: Zeiger auf eine Klasse
Zitat:
Delphi-Quellcode:
Ist das Prinzip jetzt klar?
var
A,B: array of integer; begin SetLength(A, 3); A[0] := 1; A[1] := 2; A[2] := 3; writeln('A: ', A[0], ', ', A[1], ', ', A[2]); // => A: 1, 2, 3 // REFERENZ B := A; writeln('B: ', B[0], ', ', B[1], ', ', B[2]); // => B: 1, 2, 3 B[1] := 42; writeln('B: ', B[0], ', ', B[1], ', ', B[2]); // => B: 1, 42, 3 writeln('A: ', A[0], ', ', A[1], ', ', A[2]); // => A: 1, 42, 3 // KOPIE B := Copy(A, 0, length(B)); B[0] := 2; B[1] := 5; B[2] := 7; writeln('B: ', B[0], ', ', B[1], ', ', B[2]); // => B: 2, 5, 7 writeln('A: ', A[0], ', ', A[1], ', ', A[2]); // => A: 1, 42, 3 end. |
AW: Zeiger auf eine Klasse
Okay, ich hab verstanden was du meinst. Es gab aber eine Besonderheit bei mir:
Der SetLength(...) Befehlt sorgt scheinbar dafür, dass neuer Speicher reserviert wird. Deshalb gabs bei mir arge Probleme. Dazu folgendes Beispiel:
Delphi-Quellcode:
type TCoord_XY = record
x,y:Double; end; type TPoints = Array of Array of TCoord_XY; PPoints = ^TPoints; //... procedure TForm1.FormCreate(Sender: TObject); var PointsRotor: TPoints; Ptr3:TPoints; begin SetLength(PointsRotor, 1,1); //Setze Größe des Arrays direkt PointsRotor[0,0].x:=1; //Schreibe was in das Array... //... //Variante 3 Ptr3:=PointsRotor; SetLength(Ptr3,4,1);// Ptr3 bekommt neuen Speicher zugewiesen?!? Ptr3[0,0].x:=2; //keine Auswirkung auf PointsRotor... PointsRotor[0,0] ist immernoch 1 //Variante 4 SetLength(Ptr3,4,1); Ptr3:=PointsRotor; Ptr3[0,0].x:=3; //Pointsrotor wird verändert end; end. |
AW: Zeiger auf eine Klasse
Wieso verwendest du keine Klassen im Sinne der objekt-orientierten Programmierung?
In deinem Beitrag #1 redest du von Motoren und dessen Geometrie. Warum gibt es dann keine Klasse TMotor oder T3DShape? Diese Art zu denken man bräuchte einen Zeiger auf ein Array auf ein Array mit Records von x,y-Koordinaten nennt man ![]() Code und Datenstruktur sind nicht miteinander verbunden sondern getrennt. Das führt zu einer Vielzahl von Fehlern, da die Datenstrukturen ungeschützt sind. In der OOP werden Daten und Code in Klassen verheiratet ("Kapselung") wobei der Code den Zugriff aus die Daten regelt. Hier mal etwas Lesestoff zu OOP: ![]() |
AW: Zeiger auf eine Klasse
Zitat:
|
AW: Zeiger auf eine Klasse
Zitat:
![]() |
AW: Zeiger auf eine Klasse
Ein kleines Beispiel mit Objekten:
Delphi-Quellcode:
type
TCoord_XY = record //Speichert eine X-Y-Koordinate x,y: Double; end; TPoints = class(TObject) private FItems: array of array of TCoord_XY; function GetItems(x, y: Integer): TCoord_XY; procedure SetItems(x, y: Integer; AValue: TCoord_XY); function GetSizeX: Integer; function GetSizeY: Integer; public procedure Assign(AValue: TPoints); procedure SetSize(x, y: Integer); property Items[x, y: Integer]: TCoord_XY read GetItems write SetItems; default; property SizeX: Integer read GetSizeX; property SizeY: Integer read GetSizeY; end; TRotor = class(TObject) private FPoints: TPoints; public property Points: TPoints read FPoints write FPoints; end; function Coord_XY(x, y: Double): TCoord_XY; implementation function Coord_XY(x, y: Double): TCoord_XY; begin Result.x := x; Result.y := y; end; procedure TPoints.Assign(AValue: TPoints); begin FItems := Copy(AValue.FItems); end; function TPoints.GetItems(x, y: Integer): TCoord_XY; begin Result := FItems[x, y]; end; procedure TPoints.SetItems(x, y: Integer; AValue: TCoord_XY); begin FItems[x, y] := AValue; end; function TPoints.GetSizeX: Integer; begin Result := Length(FItems); end; function TPoints.GetSizeY: Integer; begin if Length(FItems) > 0 then Result := Length(FItems[0]) else Result := 0; end; procedure TPoints.SetSize(x, y: Integer); begin SetLength(FItems, x, y); end; procedure Test; var Points1, Points2: TPoints; Rotor1, Rotor2, Rotor3: TRotor; begin Points1 := nil; Points2 := nil; Rotor1 := nil; Rotor2 := nil; Rotor3 := nil; try {erstes Punkte-Objekt erzeugen} Points1 := TPoints.Create; Points1.SetSize(1, 1); Points1[0, 0] := Coord_XY(1, 0); {Rotor mit erstem Punkte-Objekt erzeugen} Rotor1 := TRotor.Create; Rotor1.Points := Points1; {Rotor mit erstem Punkte-Objekt erzeugen} Rotor2 := TRotor.Create; Rotor2.Points := Points1; {zweites Punkte-Objekt erzeugen} Points2 := TPoints.Create; {bekommt eine Kopie der Punkte des ersten Objekts} Points2.Assign(Points1); {die Kopie wird verändert} Points2.SetSize(3, 1); Points2[2, 0] := Coord_XY(3, 0); {Rotor mit zweitem Punkte-Objekt erzeugen} Rotor3 := TRotor.Create; Rotor3.Points := Points2; {Points1 und damit Rotor1.Points und Rotor2.Points verändern, aber nicht Points2 und Rotor3.Points} Points1.SetSize(2, 1); Points1[1, 0] := Coord_XY(2, 0); finally Rotor1.Free; Rotor2.Free; Rotor3.Free; Points1.Free; Points2.Free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:37 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