![]() |
TObjectList-Object da, aber beim Zugriff Stack-Overflow
Hi,
ich habe eine TObjectList nach diesem Schema:
Delphi-Quellcode:
Explizit geht es um die Funktion:
type
TTemperatur=class private FTemp: Extended; FId: string; procedure SetId(const Value: string); procedure SetTemp(const Value: Extended); public constructor Create; procedure WriteToStream(st: TStream); procedure LoadFromStream(st: TStream); published property Id: string read FId write SetId; property Temp: Extended read FTemp write SetTemp; end; type TTemperaturList=class(TObjectList) function getItem(index: Integer): TTemperatur; virtual; procedure setItem(index: Integer; Temperatur: TTemperatur); virtual; public property Items[index: Integer]: TTemperatur read getItem write setItem; default; procedure Insert(index: Integer; Temperatur: TTemperatur); virtual; function Add(Temperatur: TTemperatur): Integer; virtual; function Remove(Temperatur: TTemperatur): Integer; virtual; function IndexOf(Temperatur: TTemperatur): Integer; virtual; function First: TTemperatur; virtual; function Last: TTemperatur; virtual; procedure WriteToStream(st: TStream); procedure LoadFromStream(st: TStream); function IndexOfId(value: string): Integer; virtual; end; type TRaspberry=class private FName: string; FTemp: TTemperaturList; FIP: string; procedure SetIP(const Value: string); procedure SetName(const Value: string); procedure SetTemp(const Value: TTemperaturList); public constructor Create; destructor Destroy; procedure WriteToStream(st: TStream); procedure LoadFromStream(st: TStream); published property Name: string read FName write SetName; property IP: string read FIP write SetIP; property Temp: TTemperaturList read FTemp write SetTemp; end; type TRaspberryList=class(TObjectList) function getItem(index: Integer): TRaspberry; virtual; procedure setItem(index: Integer; Raspberry: TRaspberry); virtual; public property Items[index: Integer]: TRaspberry read getItem write setItem; default; procedure Insert(index: Integer; Raspberry: TRaspberry); virtual; function Add(Raspberry: TRaspberry): Integer; virtual; function Remove(Raspberry: TRaspberry): Integer; virtual; function IndexOf(Raspberry: TRaspberry): Integer; virtual; function First: TRaspberry; virtual; function Last: TRaspberry; virtual; procedure WriteToFile(Filename: string); procedure LoadFromFile(Filename: string); function IndexOfIP(value: string): Integer; virtual; end;
Delphi-Quellcode:
der TTemperaturList.
function TTemperaturList.IndexOfId(value: string): Integer;
var I: Integer; begin Result:=-1; for I := 0 to self.Count-1 do if self[I].Id=value then begin Result:=I; Exit; end; end; Jetzt sollen mit folgender Prozedur TTemperatur-Items hinzugefügt, bzw. wenn sie schon vorhanden sind, geändert werden:
Delphi-Quellcode:
Ein TRaspberry wird manuell erzeugt, ist also vorhanden.
procedure TfrmMain.btn1Click(Sender: TObject);
var r, t: integer; Raspberry: TRaspberry; Temp: TTemperatur; FIP, FId: string; FTemperatur: Extended; begin FIP:='192.168.0.110'; FId:='28-000444e3ba3ff'; FTemperatur:=19.937; r:=FRaspberrys.IndexOfIP(FIP); if r>-1 then begin Raspberry:=FRaspberrys[r]; end else begin Raspberry:=TRaspberry.Create; FRaspberrys.Add(Raspberry); end; if Raspberry<>nil then begin t:=Raspberry.Temp.IndexOfId(FId); //<---Hier tritt beim zweiten durchlauf dann die Exception auf. if t>-1 then begin Temp:=Raspberry.Temp[t]; end else begin Temp:=TTemperatur.Create; Raspberry.Temp.Add(Temp); end; if Temp<>nil then begin Temp.Id:=FId; Temp.Temp:=FTemperatur; end; end; end; Beim TTemperaturList.IndexOfId(value: string) kommt es beim zweiten Aufruf der btn1Click zu einem Stackoverflow. Klar beim ersten mal wird das neue Objekt TTemperatur angelegt, weil eben noch keines vorhanden ist. Beim zweiten Mal müsste er es ja finden, da die Id die gleich ist. Komischerweise wird in der IndexOfId als Count auch 1 ausgegeben, aber auf das Object kann ich nicht zugreifen. Also irgendwo hab ich einen Denkfehler, aber ich finde ich einfach nicht. |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Zitat:
Robuster wäre es die Containerklasse nicht von der Klasse TObjectList abzuleiten sondern eine interne (private) TObjecList Instanz zu benutzen. Das entkoppelt die API der TObjectList und sichert den Client-Code besser gegen "versehentliche" Verwendung von TObjectList Methoden ab. Das könnte auch für die konkrete Fehlersuche hilfreich sein. |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Danke für deine Hilfe. Den eigentlichen Fehler habe ich mittlerweile gefunden: es war lediglich ein fehlendes inherited beim Zugriff auf das TTemperaturobjekt.
Zitat:
|
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Bei mir sind Container immer z.B. so aufgebaut:
Delphi-Quellcode:
Von aussen hin kann ich dann gezielt nur die von meiner Klasse definierten Funktionen und Prozeduren aufrufen. Dass innen eine TObjectList oder etwas anderes enthalten ist, soll der Client nicht sehen können.
type
TTemperaturList=class(TObject) private Liste: TObjectList; ... public constructor Create; destructor Destroy; override; |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Ich denke er meint, dass du eine Objektlist in deiner neuen Klasse kapselst. So kann man ganz gut die eventuelle Object-Casterei verbergen.
Edit:Und war sogar selber schneller als ich...
Delphi-Quellcode:
type
TTemperaturList=class ObjectList:TObjectList; public constructor create; function count:integer; end; TTemperaturList.create; begin ObjectList:=TObjectList.create; end; TTemperaturList.count:integer; begin Result:=ObjectList.Count; end; Andere Bemerkung, wenns erlaubt ist: Was mich an deinem Klassenkonstrukt stört ist was für verschiedene Dinge nicht alles Temp heißen. Da hat ich nämlich auch Probleme deinen QT nachzuvollziehen. |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Delphi-Quellcode:
Die Methoden getItem und setItem brauchen nicht als published declariert werden, eventuell fehlt hier das private. Published wird nicht benötigt ausser man möchte die Klasse über das Delphi DFM Streaming oder klassische RTTI ansprechen.
type
TTemperaturList=class(TObjectList) function getItem(index: Integer): TTemperatur; virtual; procedure setItem(index: Integer; Temperatur: TTemperatur); virtual; public property Items[index: Integer]: TTemperatur read getItem write setItem; default; procedure Insert(index: Integer; Temperatur: TTemperatur); virtual; function Add(Temperatur: TTemperatur): Integer; virtual; function Remove(Temperatur: TTemperatur): Integer; virtual; ... |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Da der TE wohl XE4 verwendet, wäre sicher auch die generische Objektliste aus der Unit System.Generics.Collections einen Blick Wert.
Damit könnte man sich die Schreibarbeit für Add/Remove/IndexOf etc. ersparen. |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
@mjustin:
das Private fehlt tatsächlich. Eigentlich kommen bei mir die Getter und Setter immer in Private, hatte ich lediglich vergessen. (hätte bei dem fehlenden Inherited aber nichts geändert). Aber ich weiß jetzt was du meinst. Klar kann man das auch über Generics verwenden. Aber ich habe mich so an meine ObjectList gewöhnt.... Und, zugegeben, der Variablenname Temp ist sicherlich nicht der schlaueste, aber man kann das schon lesen ;) |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Nur so als Tip:
Wenn man Klassen mit Stream-Funktionen ausstattet, dann sollte man auch immer das Interface ![]() Macht auf jeden Fall das Leben leichter ;) |
AW: TObjectList-Object da, aber beim Zugriff Stack-Overflow
Zitat:
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:31 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