Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Finden von Instanzen / Weiteres Problem (s.u.)
Matclou - Mi 10.08.11 14:20
Titel: Finden von Instanzen / Weiteres Problem (s.u.)
Hallo,
ich habe eine Frage zum Finden von Instanzen!
Und zwar müsste es ja eigentlich eine Möglichkeit, alle Instanzen einer Klasse irgendwie aufzulisten. Funktioniert das auch mit FindComponent? Oder gibt es da noch andere Methoden, mit denen man auf bestehende Instanzen zugreifen kann?
Habe wohl eine etwas ältere Delphi-Version. Kann leider nicht genau sagen, welche es ist, weil ich sie gerade nicht vorliegen habe. Müsste aber, soweit ich mich erinnere 6 sein.
Vielen Dank im Voraus für die Hilfe!
Moderiert von
Narses: Topic aus Sonstiges (Delphi) verschoben am Mi 10.08.2011 um 16:59
Narses - Mi 10.08.11 17:03
Moin!
Matclou hat folgendes geschrieben : |
Und zwar müsste es ja eigentlich eine Möglichkeit, alle Instanzen einer Klasse irgendwie aufzulisten. |
Nein, AFAIR gibt es in Delphi keine Möglichkeit eine Liste der instanziierten Klassen zu erhalten (das ist ja im Wesentlichen das, was auf dem Heap liegt). Einige separate Speichermanager (z.B. FastMM4) können nicht wieder freigegebene Instanzen beim Programmende auflisten, aber das war´s auch schon. :nixweiss:
Fazit: Du musst dir beim Erzeugen von Instanzen diese merken und selbst wieder freigeben. :idea:
cu
Narses
Matclou - Mi 10.08.11 17:37
Ich hab's schon fast befürchtet^^ Habe allerdings eine Notlösung im Hinterkopf: Ich nehme als Oberklasse meiner Klasse einfach die Klasse tImage und lasse die Eigenschaft visible einfach auf Dakar stehen... Das müsste man dann ja auch als Komponente auflisten lassen können mit den entspr. Methoden.
Xion - Mi 10.08.11 18:27
Ich verstehe zwar nicht ganz was du vor hast (Dakar?) aber es hört sich so an, als wolltest du per FindComponent deine eigenen Objekte suchen.
Warum machst du nicht ein array mit deinen Instanzen?
Oder auch möglich, du machst dir eine Factory als Oberklasse, die dann dieses Array intern hält. Dann siehst du davon außen nix. Von außen hättest du dann sowas in der Art:
Delphi-Quelltext
1: 2:
| Fabrik.ErzeugeEinNeuesObjekt; Fabrik.AlleObjekteLöschen; |
Jetzt könnte man darin noch mehr verstecken, so dass man dann z.B. schnell ein bestimmtes Objekt suchen könnte. Oder alle Objekte um eins nach rechts rücken... Je nachdem was du vorhast.
Matclou - Mi 10.08.11 19:59
Dakar klingt doch einfach klasse! :D Nein, mein iPod hat eine sehr dämliche Autokorrektur, die mir gewissermaßen meine Mündigkeit abnimmt ein Wort richtig zu schreiben^^ Schon seltsam wie er von "false" auf "Dakar" kommt ;)
Trotzdem hast du die Idee richtig verstanden. Was deinen Vorschlag angeht:
Auf die Idee bin ich irgendwie noch gar nicht gekommen^^^
Verstehe ich das richtig: Ich müsste also, wenn eine Instanz einer Klasse zur Laufzeit erstellt wird, gleichzeitig das Objekt quasi zur Sortierung in einem Array speichern?
Es müsste sich also um folgende Variable handeln:
Delphi-Quelltext
1:
| var ArrayMeineKlasse : array of tMeineKlasse |
Und gespeichert werden müsste das Objekt dann zu diesem Zeitpunkt:
Delphi-Quelltext
1: 2:
| NeueInstanz:=tMeineKlasse.create; array[0]:=NeueInstanz |
Ich bin etwas eingerostet, gab es zwischen ein- und zweidimensionalen Arrays irgendeinen Unterschied bei der Deklaration?
Lemmy - Do 11.08.11 06:02
Guten Morgen,
für so was nimmt man im allgemeinen kein Array sondern eine TObjectList. Ist wesentlich einfacher zu handhaben.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var oList:TObjectLIst; ....
var oTest:TMeineKlasse; begin oTest:=TMeineKlasse.Create; oList.Add(oTEst); ... |
Vorteile gegenüber Array: Es sind bel. viele Elemente erlaubt und man muss sich nicht wie bei einem dynamischen Array um den Speicherplatz kümmern. Gibt man bei der Erzeugung der Liste noch den Parameter beim Create an, werden die Objekte in der liste auch automatisch freigegeben.
Grüße
Xion - Do 11.08.11 08:48
Matclou hat folgendes geschrieben : |
Delphi-Quelltext 1:
| var ArrayMeineKlasse : array of tMeineKlasse |
Und gespeichert werden müsste das Objekt dann zu diesem Zeitpunkt:
Delphi-Quelltext 1: 2:
| NeueInstanz:=tMeineKlasse.create; array[0]:=NeueInstanz | |
Das reicht schon:
Delphi-Quelltext
1:
| ArrayMeineKlasse[0] := TMeineKlasse.Create; |
Matclou hat folgendes geschrieben : |
Ich bin etwas eingerostet, gab es zwischen ein- und zweidimensionalen Arrays irgendeinen Unterschied bei der Deklaration? |
Zweidimensional wäre:
Delphi-Quelltext
1:
| var ArrayMeineKlasse: array of array of TMeineKlasse; |
Matclou - Fr 12.08.11 22:24
Lemmy hat folgendes geschrieben : |
Guten Morgen,
für so was nimmt man im allgemeinen kein Array sondern eine TObjectList. Ist wesentlich einfacher zu handhaben.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var oList:TObjectLIst; ....
var oTest:TMeineKlasse; begin oTest:=TMeineKlasse.Create; oList.Add(oTEst); ... |
Vorteile gegenüber Array: Es sind bel. viele Elemente erlaubt und man muss sich nicht wie bei einem dynamischen Array um den Speicherplatz kümmern. Gibt man bei der Erzeugung der Liste noch den Parameter beim Create an, werden die Objekte in der liste auch automatisch freigegeben.
Grüße |
Okay, das klingt ja ganz gut! Wie viele Elemente sind denn bei arrays erlaubt?
Und: Kann man in der ObjectList auch einfache Integerzahlen einschreiben oder geht das nicht?
EDIT: Das letzte dürfte nicht gehen, ich kann es mir auf jeden Fall nur schwerlich vorstellen. Seit welcher Delphi-Version gibt es die tOBjectList denn eigentlich? Die Frage scheint mir auch noch wichtig zu sein ;)
Vielen Dank im Voraus für die Hilfe!
Lemmy - Fr 12.08.11 23:00
Matclou hat folgendes geschrieben : |
Okay, das klingt ja ganz gut! Wie viele Elemente sind denn bei arrays erlaubt?
|
ich arbeite schon lange nicht mehr mit Arrays, aber dynamische Arrays heißen eben so weil sie theoretisch bel. groß werden können - so groß wie dein Arbeitsspeicher ausreicht...
Matclou hat folgendes geschrieben : |
Und: Kann man in der ObjectList auch einfache Integerzahlen einschreiben oder geht das nicht? |
Nicht wirklich - deshalb heißt das ja auch TObjectList. Es gibt nen Trick, aber das würde ich nicht empfehlen, weil das dann Stellen sind an denen später Fehler auftreten oder die dann ausgebessert/geändert werden, wenn ein bestimmtes Verhalten geändert wird.
Typisches Beispiel aktuell: Jede Komponente der VCL hat ein Tag-Property. Das ist ein Integer. Nun ist es so, dass Zeiger ebenso im Grunde 32Bit Integer sind mit der Adresse auf die sie zeigen. Und so war es kein Problem einem Tag-Property einen Zeiger zuzuweisen.
Jetzt kommt der 64Bit Compiler - da geht das dann aber schief, weil der Integer 32Bit-breit bleibt, der Zeiger aber 64-Bit breit ist, was dann zu lustigen Auswirkungen und im besten Fall in einer klaren Fehlermeldung endet...
Matclou hat folgendes geschrieben : |
Seit welcher Delphi-Version gibt es die tOBjectList denn eigentlich? Die Frage scheint mir auch noch wichtig zu sein ;)
|
In Delphi 5 ist sie auf jeden Fall dabei. Du musst die Unit contnrs einbinden. Und sollte es TObjectList nicht geben, dann kannst Du immer noch die TList nehmen, die sollte eigentlich auch schon bei Delphi 3 dabei sein...
Grüße
*Nachtrag
Wenn du unbedingt Texte oder Zahlen zu deinem Objekt speichern willst, dann kannst Du auch eine TStringList nehmen - in die kannst Du bel. Texte und auch Objekte an einer Position speichern. Allerdings weiß ich nicht auswendig, ob das in den älteren Delphi_Versionen schon geht...
Matclou - So 14.08.11 13:19
Folgendes: Ich lasse Objekte vom Typ tKomponist aus der Objektliste olkomponisten in der ListBox lbkomponisten anzeigen. Das funktioniert einwandfrei. Wenn ich aber einen Komponisten löschen will, wird eine Fehlermeldung angezeigt: "Format '%p' ungültig oder nicht kompatibel mit Argument".
Es liegt offensichtlich an der Programmzeile "olkomponisten.delete(i)". Delete ist offiziell keine Methode von tobjectlist sondern eine von tlist vererbte. In der Delphi-Hilfe heißt es: "Mit Delete wird das Element an der bezeichneten Position aus der Liste gelöscht.".
Müsste doch eigentlich funktionieren, oder? Was mache ich falsch? Und: Wird mit Delete nur der Listeneintrag oder auch das Objekt gelöscht. Sonst wäre ja "hilfkomponist.destroy" unnötig.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TGUI.BtKomponistloeschenClick(Sender: TObject); var hilf: string; var hilfobjekt: tobject; var hilfkomponist: tkomponist; var i,j: integer; begin hilf:=Lbkomponisten.Items[Lbkomponisten.ItemIndex]; for i:=0 to anzahlkomponisten-1 do begin hilfobjekt:=OlKomponisten.Items[i]; hilfkomponist:=tkomponist(hilfobjekt); if hilfkomponist.getname = hilf then begin lbkomponisten.deleteselected; olkomponisten.delete(i); hilfkomponist.destroy; end; end; |
Nachtrag: Ohne das hilfskomponist.destroy und mit einem kleinem Zusatz funktioniert es jetzt ;) War nur ein "Variablenfehler", wenn ich das mal so nennen darf ;)
jaenicke - So 14.08.11 13:33
Erstens: Wenn du dem Konstruktor deiner Objektliste als Parameter True mitgibst, wird das Objekt beim Entfernen aus der Liste auch freigegeben.
Zweitens: Wie auch in der Delphi-Hilfe steht, sollte Destroy niemals direkt aufgerufen werden, sondern immer Free oder FreeAndNil.
Matclou - So 14.08.11 13:55
Gut, danke für die beiden Hinweise ;)
Ich bekomme nun übrigens beim Löschen regelmäßig den Hinweis der Listenindex überschreite das Maximum...
Der Listenindex kann sich ja im Prinzip nur auf die tobjectlist beziehen, oder? Eine Listbox hätte da doch andere Bezeichnungen, oder?
---
Moderiert von
Narses: Beiträge zusammengefasst---
Hier nochmal alle relevanten Methoden und Delkarationen!
BtKomponistenClick -> Erstellt neues Objekt, aktualisiert die Liste
BtKomponistloeschenClick -> Löscht Objekt und seinen Namen aus der Liste
einfuegen -> fügt ein neues Objekt an der richtigen Stelle in die Objektlist ein, nimmt hierfür eine unsichtbare, sortierte Listbox zur Hilfe
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: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110:
| uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, mkomponist, Contnrs, ExtCtrls ;
type TGUI = class(TForm) BtWerk: TButton; BtKomponist: TButton; BtInterpret: TButton; BtCD: TButton; LabKomponistenname: TLabel; EdKomponistenname: TEdit; Lbkomponisten: TListBox; EdKomponistensortierung: TEdit; LabKomponistensortierung: TLabel; LbKomponistenSortieren: TListBox; BtKomponistInfobutton: TButton; LabKomponistenInfoName: TLabel; LabKomponistenInfoSortierung: TLabel; LabKomponistenInfoID: TLabel; LabKomponistenInfoNameBeschriftung: TLabel; LabKomponistenInfoSortierungBeschriftung: TLabel; LabKomponistenInfoIDBeschriftung: TLabel; BtKomponistloeschen: TButton; procedure BtKomponistClick(Sender: TObject); procedure BtAktualisierenLbKomponistenClick(Sender: TObject); procedure FormActivate(Sender: TObject); procedure BtKomponistInfobuttonClick(Sender: TObject); procedure BtKomponistloeschenClick(Sender: TObject); private procedure einfuegen(sortierung:string; komponist:tkomponist);
public OlKomponisten: tObjectList; idkomponistenfortlaufend:integer; end;
var GUI: TGUI;
implementation
{$R *.dfm}
procedure TGUI.BtKomponistClick(Sender: TObject); var NeuerKomponist,hilfskomponist: tKomponist; var hilf:integer; var hilfobjekt: tobject; begin NeuerKomponist:=tkomponist.create; Neuerkomponist.setname(Edkomponistenname.text); Neuerkomponist.setsortierung(Edkomponistensortierung.text); Neuerkomponist.setid(idkomponistenfortlaufend); einfuegen(neuerkomponist.getsortierung, neuerkomponist); idkomponistenfortlaufend:=idkomponistenfortlaufend+1; lbkomponisten.clear; for hilf:=0 to olkomponisten.count-1 do begin hilfobjekt:=OlKomponisten.items[hilf]; hilfskomponist:=tkomponist(hilfobjekt); LbKomponisten.Items.Add(hilfskomponist.getname); end; EdKomponistenname.text:=''; EdKomponistensortierung.text:=''; end;
procedure TGUI.FormActivate(Sender: TObject); begin OlKomponisten:=TObjectList.create(true); idkomponistenfortlaufend:=1; end;
procedure tgui.einfuegen(sortierung:string; komponist: tkomponist); var hilf: integer; var hilfstring: string; begin LbKomponistenSortieren.items.add(sortierung); for hilf:= 0 to lbkomponistensortieren.count-1 do begin hilfstring:=LbKomponistenSortieren.items[Hilf]; if hilfstring = sortierung then OlKomponisten.insert(hilf, komponist); end; end;
procedure TGUI.BtKomponistloeschenClick(Sender: TObject); var hilf: string; var hilfobjekt: tobject; var hilfkomponist: tkomponist; var i,j: integer; begin hilf:=Lbkomponisten.Items[Lbkomponisten.ItemIndex]; for i:=0 to olkomponisten.count-1 do begin hilfobjekt:=OlKomponisten.Items[i]; hilfkomponist:=tkomponist(hilfobjekt); if hilfkomponist.getname = hilf then begin lbkomponisten.deleteselected; olkomponisten.delete(i); end; end; end; end. |
Xion - So 14.08.11 14:30
Matclou hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TGUI.BtKomponistloeschenClick(Sender: TObject); var hilf: string; var hilfobjekt: tobject; var hilfkomponist: tkomponist; var i,j: integer; begin hilf:=Lbkomponisten.Items[Lbkomponisten.ItemIndex]; for i:=0 to olkomponisten.count-1 do begin hilfobjekt:=OlKomponisten.Items[i]; hilfkomponist:=tkomponist(hilfobjekt); if hilfkomponist.getname = hilf then begin lbkomponisten.deleteselected; olkomponisten.delete(i); end; end; end; | |
So kann das natürlich nicht gehen. Du gehst die Einträge durch, und zwar von vorne nach hinten, und löschst dabei aus der Liste raus. Am Ende willst du auf Count-1 zugreifen, es ist aber ein Eintrag weniger da. Fällt dir was auf? ;)
Probiers mal mit
for i:=olkomponisten.count-1 downto 0 do
Dann wird zwar der eine Eintrag nach dem Löschen zweimal geprüft, aber ich denke das machts nicht aus.
jaenicke - So 14.08.11 14:34
Mal so nebenbei:
Dein Quelltext sieht grauenhaft aus, keine Einrückungen... :shock:
Wenn du den besser formatieren würdest, würde man da auch schneller durchblicken...
Matclou - So 14.08.11 15:05
Hhm, ich glaube downto kennt meine Delphi-Version noch nicht ;)
Aber danke schon mal für das FInden der Fehlerquelle, ich find da schon was ;)
Narses - So 14.08.11 15:34
Moin!
Matclou hat folgendes geschrieben : |
Hhm, ich glaube downto kennt meine Delphi-Version noch nicht ;) |
Das das Turbo-Pascal schon kannte, halte ich das für unwahrscheinlich. ;) Schau nochmal genau hin... :suspect: :les: :idea:
cu
Narses
jaenicke - So 14.08.11 16:10
Oder du sagst uns was für ein Fehler in welcher Zeile kommt. ;-)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!