AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Records, Pointer, Listen & Co.

Ein Thema von Evian · begonnen am 21. Sep 2006 · letzter Beitrag vom 23. Sep 2006
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Evian
Evian

Registriert seit: 10. Apr 2003
Ort: Berlin
485 Beiträge
 
Delphi 6 Professional
 
#1

Records, Pointer, Listen & Co.

  Alt 21. Sep 2006, 23:16
Hallo Zusammen,

da ich schon seit ein paar Jahren nicht mehr mit sowas gearbeitet habe, wollt ich einfach noch mal hier nachfragen. Also ich möchte in meinem Projekt ein unbestimmte Anzahl an Informatismengen dynamisch speichern. Jede dieser Informationsmengen besteht aus einem tPoint und vier boolchen Werten, weshalb sich hier ja ein Record anbieten würde. Die einzelnen Mengen sind auch liniear mit einander verbunden, weshalb ich sie per pointer zu einer einseitigen Liste verketten könnte. Was ich nun nicht mehr ganz weiß ist: Muss ich ich, wenn ich die Informationsmengen "verwerfen" möchte, mich auch konkret selber um die "Entsorgung" kümmern, indem ich sie z.B. auf NIL setze, oder passiert das automatisch im Hintergrund?! Oder gibt es vielleicht noch einen wesentlich unkomplizierteren Weg (z.B. mit Hilfe von tList) um mein Vorhaben zu realisieren?

würde mich über ein Paar Tips sehr freuen,

grüße, Evian
-> www.Phillsoft.de

Ich bin nun Mathematiker, aber meine Freundin bleibt trotzdem unberechenbar!
  Mit Zitat antworten Zitat
Benutzerbild von tn249
tn249

Registriert seit: 18. Jan 2004
Ort: München
164 Beiträge
 
Delphi 2005 Personal
 
#2

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 01:57
Sers,

ein Weg der vielleicht etwas umständlich ist, aber ganz gut geht ist folgender:

du definierst das was du als record definieren woltest als klasse ( zb. TMyData ) und definierst den TPoint und die 4 bools als felder der klasse.

jetzt kannst du eine TObjectList anlegen. dann erzeugst du deine TMyData klassen und fügst sie der ObjectList hinzu.

der trick dabei ist einen Wert der TobjectList, der sich OwnsObject oder so ähnlich nennt , auf true zu setzen, weil dann die objectlist beim löschen einzelner items oder vernichten der gesamten liste die vorher hinzugefügten object freigibt.


wie gesagt. evtl. ist das ein overkill aber es funktioniert.

Gruß
tn249
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
bttb930

Registriert seit: 6. Okt 2003
372 Beiträge
 
#3

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 02:03
Zitat von tn249:
wie gesagt. evtl. ist das ein overkill aber es funktioniert.
Absolut falsch: Das ist kein Overkill sondern der richtige Weg: Genau so wie Du es beschrieben hast macht man das.

Und zum ersten Beitrag: Setzt Du Pointer auf nil, dann hast Du noch nicht den Speicherbereich auf den die Pointer vorher gezeigt haben frei gegeben. Aber arbeite einfach nicht explizit mit Pointern - Delphi macht das ja implizit sobald Du eine Klasse definierst. Frei geben kannst Du Klasseninstanzen indem Du deren Free-Methode aufrufst. Dabei musst Du aufpassen, dass Du nichts doppelt frei gibst. Hast Du beispielsweise das von tn249 erwähnte OwnsObjects-Feld auf True gesetzt, dann gibt die Liste alle Elemente frei, sobald sie selbst frei gegeben wird. D.h. du darfst diese nicht vorher selbst frei geben.
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#4

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 08:27
Hi Leute,

das mit dem nil funzt nur, wenn man ein dynamisches Array anlegt. Hier kann man sicher folgendes machen:
Delphi-Quellcode:
type
  TMyData = Record
    Point : TPoint;
    Param1 : Boolean;
    Param2 : Boolean;
    Param3 : Boolean;
    Param4 : Boolean;
  end;

type
  TDataList = array of TMyData;


type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
    FDataList : TDataList;
  public
    { Public-Deklarationen }
    procedure AddData(Data : TMyData);
    procedure Clear;
  end;


var
  Form1: TForm1;

implementation

{$R *.DFM}

{ TForm1 }

procedure TForm1.AddData(Data: TMyData);
begin
  IF High(FDataList) = 0 then SetLength(FDataList, 1) else
    SetLength(FDataList, Length(FDataList) + 1);
  FDataList[High(FDataList)] := Data;
end;

procedure TForm1.Clear;
begin
  FDataList := nil;
end;
Das sieht sicher recht einfach aus. Ich persönich habe aber fest gestellt, dass man immer wieder zusätzliche Methoden für den Zugriff auf die einzelnen Elemente in der Liste benötigt.

Dann kommt man von selbst auf das was bttb930 sagt. Ich benutze übrigens nur noch diese Methode.
Der Vorteil ist unter anderem, dass du häufig benötigte Functionen in dein Listenobject integrieren kannst und nebenbei natürlich schon ne Menge Funktionalität vor findest.

Ein kleines Bsp. hier:
Delphi-Quellcode:
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  contnrs;

type
  TMyData = class(TObject)
  private
    FParam1: Boolean;
    FParam4: Boolean;
    FParam2: Boolean;
    FParam3: Boolean;
    FPoint: TPoint;
  protected
  public
    Constructor Create(APoint : TPoint;
                       Param1, Param2, Param3, Param4 : Boolean); overload;
    property Point : TPoint read FPoint write FPoint;
    property Param1 : Boolean read FParam1 write FParam1;
    property Param2 : Boolean read FParam2 write FParam2;
    property Param3 : Boolean read FParam3 write FParam3;
    property Param4 : Boolean read FParam4 write FParam4;
  end;

type
  TDataList = class(TObjectList)
  private
  protected
  public
    Function GetPointfromIndex(Index : Integer):TPoint;
  end;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
    FDataList : TDataList;
  public
    { Public-Deklarationen }
    procedure AddData(Data : TMyData);
  end;


var
  Form1: TForm1;

implementation

{$R *.DFM}

{ TForm1 }

procedure TForm1.AddData(Data: TMyData);
begin
  IF not Assigned(FDataList) then Exit;
  FdataList.Add(Data);
end;

{ TMyData }

constructor TMyData.Create(APoint: TPoint; Param1, Param2, Param3,
  Param4: Boolean);
begin
  inherited create;
  FParam1 := Param1;
  FParam2 := Param2;
  FParam3 := Param3;
  FParam4 := Param4;
  FPoint := APoint;
end;

{ TDataList }

function TDataList.GetPointfromIndex(Index: Integer): TPoint;
var Data : TMyData;
begin
  // vorbelegen
  Result := Point(-1, -1);
  // bei blödsinnigem Index raus
  IF (Index < 0) or (Index >= self.Count) then Exit;
  // Typ-casting
  Data := TMyData(self.Items[Index]);
  try
    IF not assigned(Data) then Exit;
    Result := Data.Point;
  except
    Result := Point(-1, -1);
  end;
end;
o.k. ich hab mir hier jetzt das creieren und frei geben der Liste gespart, aber es soll nur mal die grundlegende Vorgehensweise zeigen. Wie in den vorherigen Beiträgen beschrieben wird jetzt mit der Freigabe der Liste automatisch auch jedes enthaltene Data-Objekt mit frei gegeben.

das wars von mir,

Gruß oki
  Mit Zitat antworten Zitat
bttb930

Registriert seit: 6. Okt 2003
372 Beiträge
 
#5

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 10:05
Ich mache es ein klein wenig anders als oki:

bei mir ist TDataList NICHT von TObjectList abgeleitet sondern ANTHÄLT eine TObjectList:

Delphi-Quellcode:
type
  TDataList = class
  private
    FList: TObjectList;

    function GetCount: Integer; // gibt FList.Count zurück
    function GetItem(Index: Integer): TMyData; // gibt FList[i] as TMyData zurück
    ...
  public
    constructor Create; // erstellt die Liste mit FList := TObjectList.Create(True{AOwnsObjects});
    destructor Destroy; // löscht die Liste mit FList.Free;
    procedure Clear; // ruft FList.Clear auf

    property Count: Integer read GetCount;
    property Items[Index: Integer]: TMyData read GetItem;
    ...
  end;
Nachteil: Ich muss alle Funktionen die ich aus der ObjectList brauche nochmal schreiben (Clear usw), die Inhalte sind aber kurz da sie ja nur die entsprechenden FList-Funktionen aufrufen (FList.Clear usw).

Vorteil: Der Benutzer dieser Klasse (das kann ja ein ganz anderer Programmierer sein) kann in diese Liste nur die von mir gewünschten Objekte einfügen, also beispielsweise nur TMyData. Andere Klassen werden - anders als beim Ableiten von TObjectList - nicht angenommen. Dafür entfällt dann der Typecast (bei oki die Zeile Data := TMyData(self.Items[Index]); die besser Data := Items[Index] as TMyData wäre aber nun Data := Items[Index] sein muss).

Wie oki das macht hab ich's früher auch gemacht, aber die Erfahrung lehrt mich, dass das zu fehlerträchtig und zuwenig flexibel ist. Ich will auch gar nicht alle public-Funktionen von TObjectList anbieten, sondern nur einen Teil, den ich dann teilweise auch verändern möchte.
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 11:56
Hi,

grundsätzlich gebe ich bttb930 recht. Bis jetzt war mir das dann aber doch zu viel Aufwand. Dazu muß ich sagen, dass ich in der Regel alleine arbeite und selten jemand meine Classen benutzen muß.

Vielleicht sollte man mal schauen, ob man dann nicht doch die paar methoden von TObjectList überschreibt. Dass könnte dann durchaus so aussehen:
Delphi-Quellcode:
type
  TMyList = class(TObjectList)
  private
  protected
  public
    function Add(AObject: TMyData): Integer;
  end;


{ TMyList }

function TMyList.Add(AObject: TMyData): Integer;
begin
  Result := inherited Add(AObject);
end;
Das ist dann so ala TObjectList aus TList. Alle weiteren Methoden die spezielle Relevanz haben müßten dann natürlich auch überschrieben werden.

Ich will jetzt nicht den Eindruck erwecken unbedingt eine andere Methode als bttb930 nach Vorne zu bringen. Bis heute überschreibe ich auch keine Methoden von TObjectList (warum eigentlich nicht ). dieser Weg viel mir gerade so ein, und ich find ihn gar nicht so schlecht.


Gruß oki
  Mit Zitat antworten Zitat
bttb930

Registriert seit: 6. Okt 2003
372 Beiträge
 
#7

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 12:26
Das Überschreiben ist in diesem Fall aber gefährlich, da die Methode Add NICHT als virtual deklariert ist. Das heißt Du kannst in Deinem Beispiel per Liste.Add(...) zwar nur TMyDatas in die Liste eintragen, per (Liste as TObjectList).Add(...) aber beliebige TObjects. Und das passiert schneller als man denkt, nicht unbedingt durch expliziten TypeCast aber etwa wenn Du eine andere Prozedur hast, die als Parameter eine TObjectList erwartet. Der könntest Du Deine TMyList übergeben (ist ja eine TObjectList), wenn diese Prozedur aber Add aufruft, dann eben nicht TMyList.Add sondern TObjectList.Add.
  Mit Zitat antworten Zitat
Benutzerbild von Evian
Evian

Registriert seit: 10. Apr 2003
Ort: Berlin
485 Beiträge
 
Delphi 6 Professional
 
#8

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 12:52
hui, da ist ja doch einiges Zusammen gekommen. Werd nachher erstmal die Vorschlag von Oki umsetzen und sofern es noch irgendwelche Probleme gibt, werd ich mich noch mal melden.

Aber vielen Danke erstmal, für die ausführlichen Beschreibungen.
-> www.Phillsoft.de

Ich bin nun Mathematiker, aber meine Freundin bleibt trotzdem unberechenbar!
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#9

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 13:33
Hi,

um es gleich klar zu stellen; bttb hat Recht!

Gut, und nun mein Aber:

Zitat von bttb930:
Und das passiert schneller als man denkt, nicht unbedingt durch expliziten TypeCast aber etwa wenn Du eine andere Prozedur hast, die als Parameter eine TObjectList erwartet. Der könntest Du Deine TMyList übergeben (ist ja eine TObjectList), wenn diese Prozedur aber Add aufruft, dann eben nicht TMyList.Add sondern TObjectList.Add.
Wer das macht hat selber Schuld. Mein Object ist eben nicht eine ordinäre TObjectList. Grundsätzlich benenne ich diese Listen immer nach ihrem "Inhalt".

Das muß man sich so vorstellen, dass ich eine Liste der Personen auch TPersonenListe nenne. Ich selber gehe davon aus, dass jemand in einen Behälter nur das gibt, was da rein gehört. Wer in den Kühlschrank die Wäsche legt, hat selber schuld. Da ich aber auch versuche möglichst DAU-sicher zu proggen gebe ich im Grunde bttb recht. In wie Weit mein Vorschlag zum Überschreiben Konventionssicher ist, weis ich auch nicht.

Gruß oki
  Mit Zitat antworten Zitat
bttb930

Registriert seit: 6. Okt 2003
372 Beiträge
 
#10

Re: Records, Pointer, Listen & Co.

  Alt 22. Sep 2006, 14:25
naja, mit DAUs hat das nicht viel zu tun, aber wenn ich alleine programmiere bin ich auch gerne mal faul.

nur programmiere ich idR im team mit 5-10 anderen entwicklern - und da rächen sich faulheiten früher oder später immer. egal ob DAUs im team sind oder nicht.

grundsätzlich überschreibt man nicht-virtuelle funktionen und prozeduren nicht.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:29 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz