![]() |
dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Hallo liebe Community,
ich brauch eure Hilfe zu folgendem Problem: Ich will eine Fahrstuhlsteuerung programmieren, die eine beliebige Anzahl von Fahrstühlen, Etagen etc. verwalten & steuern kann. Die Lösung soll dabei objektorientiert gelöst werden. Daher war mein erster Gedanke bei der Steuerungsklasse eine Liste aller Fahrstühle einzufügen. Das sieht momentan so aus:
Code:
Die Liste wird dabei folgendermaßen angelegt:
//_______Steuerung__________________
pTFstKa = ^VFstKa; VFstKa = record FstKaX: ^Fahrstuhlkabine; //Fahrstuhlkabine ist als Klasse deklariert next: PTFstKa; end; Steuerung = class id: cardinal; pFstKa: pTFstKa; procedure Fahrstuhl_Hinzu(id_in:cardinal; zulGewicht_in, EtageV_in, EtageB_in: integer; sNiAnEt: string); function Suche_Fahrstuhl(Suchkriterium, id_in, Stelle: cardinal):pTFstKa; constructor init(id_in: cardinal); destructor destruct(); end;
Code:
Wenn ich nun mithilfe der Liste auf eine Instanz der Klasse "Fahrstuhlkabine" zugreife, bekomm ich leider eine Zugriffs-Exception.
procedure Steuerung.Fahrstuhl_Hinzu(id_in:cardinal; zulGewicht_in, EtageV_in, EtageB_in: integer; sNiAnEt: string);
var FstKa: Fahrstuhlkabine; p,h: pTFstKa; begin //Listenelement hinzufügen p:=pFstKa; new(h); h^.next:=nil; //Objektinitialisierung: FstKa:= Fahrstuhlkabine.Init(id_in, zulGewicht_in, EtageV_in, EtageB_in, sNiAnEt); h^.FstKaX:= @FstKa; //an Liste anfügen if pFstKa=nil then pFstKa:=h else begin while p^.next<>nil do begin p:=p^.next; end; p^.next:=h; end; end;
Code:
Mit google konnte ich mein Problem leider nicht bewältigen. Lediglich hab ich herausgefunden, dass es schon vorgefertigte Listen(-arten) gibt. Daher: Bitte helft mir! :wink:
//________Laden der Aufzug-Eigenschaften des darzustellenden Aufzugs__________
index:= Combob_FstKa.ItemIndex; p1:= Steuerung1.Suche_Fahrstuhl(2,0,index); Form.Caption:= 'Aufzug - Nr:' + inttostr(p1^.FstKaX^.id); // <------ hier kommt dann die Exception .... Danke schonmal im Vorraus. Grüße Ric Edit: Falls mein Problem nicht deutlich geworden ist o.Ä. bitte nachfragen. Hauptsache ich bekomm ein Feedback. Danke! |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Hallo und Willkommen in den heiligen Hallen des Wissens und des Wahnsinns :love:
Delphi-Quellcode kannst du in (Delphi)(/Delphi)-Tags (mit eckigen Klammern) packen. Das tue ich hier einmal, mit leichten Formatierungsänderungen: Teil "Steuerung"
Delphi-Quellcode:
"Liste anlegen"
pTFstKa = ^VFstKa;
VFstKa = record FstKaX: ^Fahrstuhlkabine; //Fahrstuhlkabine ist als Klasse deklariert next: PTFstKa; end; Steuerung = class id: cardinal; pFstKa: pTFstKa; procedure Fahrstuhl_Hinzu( id_in:cardinal; zulGewicht_in, EtageV_in, EtageB_in: integer; sNiAnEt: string); function Suche_Fahrstuhl(Suchkriterium, id_in, Stelle: cardinal):pTFstKa; constructor init(id_in: cardinal); destructor destruct(); end;
Delphi-Quellcode:
"Laden der Aufzug-Eigenschaften des darzustellenden Aufzugs"
procedure Steuerung.Fahrstuhl_Hinzu(
id_in:cardinal; zulGewicht_in, EtageV_in, EtageB_in: integer; sNiAnEt: string ); var FstKa: Fahrstuhlkabine; p,h: pTFstKa; begin //Listenelement hinzufügen p:=pFstKa; new(h); h^.next:=nil; //Objektinitialisierung: FstKa:= Fahrstuhlkabine.Init(id_in, zulGewicht_in, EtageV_in, EtageB_in, sNiAnEt); h^.FstKaX:= @FstKa; //an Liste anfügen if pFstKa=nil then pFstKa:=h else begin while p^.next<>nil do begin p:=p^.next; end; p^.next:=h; end; end;
Delphi-Quellcode:
index := Combob_FstKa.ItemIndex;
p1 := Steuerung1.Suche_Fahrstuhl(2,0,index); Form.Caption := 'Aufzug - Nr:' + inttostr(p1^.FstKaX^.id); // <------ hier kommt dann die Exception Wieviel Theoriewissen über Objektorientierung und Anforderungserhebung habt ihr mit auf den Weg bekommen? Die Anforderung von dir sagt "Fahrstuhlsteuerung, die eine beliebige Anzahl von Fahrstühlen, Etagen etc. verwalten & steuern kann". Kannst du mehr dazu erzählen? Gerade zur Methode
Delphi-Quellcode:
und insbesondere den Parametern kann ich mir spontan gar nichts vorstellen :gruebel:
Steuerung.Suche_Fahrstuhl(..)
Zur Lösung des eigentlichen Problems: Entweder bin ich dumm (zum Ausgleich bin ich aber relativ schön), oder aus dem hier ersichtlichen Code lässt sich nichts finden. Meine Vermutung wäre, dass
Delphi-Quellcode:
keinen vernünftigen Zeiger zurückgibt, beispielsweise den Record nicht mittels
Steuerung.Suche_Fahrstuhl(..)
Delphi-Quellcode:
auf dem Heap anlegt, sondern nur lokal "bei sich" auf dem Stack und dann einen Pointer auf Schrott zurückgibt.
new()
Alternativ streicht bei mir der Debugger immer wieder gerne eine Zeile zu tief an, meint in Wirklichkeit die Zeile darüber. Setz doch mal einen Haltepunkt auf
Delphi-Quellcode:
und geh dann schrittweise mit F7 durch und schau wo er rausfliegt.
p1 := Steuerung1.Suche_Fahrstuhl(2,0,index);
Das bringt mich dann zu einem an sich erst einmal subjektiven Thema, hoffe aber, dass der Großteil der Belegschaft hier das ähnlich sieht: Ich finde den Code extrem schwer zu lesen, warum überhaupt die Records (und Zeiger)? Und warum keine gängigen Listentypen wie
Delphi-Quellcode:
oder
TList
Delphi-Quellcode:
? Ist das eine zwingende Vorgabe? Man muss doch nicht in jedem Projekt die verkettete Liste neu erfinden...
TObjectList
Zu Stilvorgaben und Namenskonventionen: Wie lange bist du schon bei Delphi dabei und von welcher Sprache kommst du? Mir kam es anfangs auch etwas dämlich vor, die Klassennamen immer mit T beginnen zu lassen, das ist sicher auch persönliches Gusto. Aber ich kann mir spontan keinen (hier passenden) Grund ausdenken, Konstruktoren und Destruktoren nicht
Delphi-Quellcode:
und
Create
Delphi-Quellcode:
zu nennen, das bietet auf Dauer nur Verwirrungspotentiel.
Destroy
Wenn ich jetzt noch damit anfange, dass zumindest mein Kopf es spontan nicht schafft, den Zweck hinter Variablennamen wie
Delphi-Quellcode:
oder
sNiAnEt
Delphi-Quellcode:
zu erkennen, wendest du dich wahrscheinlich wie jeder vernünftige Mensch angewidert vom Forum (insbesondere von mir) ab, da du eigentlich aus einem anderen Grund hergekommen bist. Aber ich denke dass es viel schwerer ist, überhaupt durcheinander zu kommen, wenn man nicht an Buchstaben spart und außen am Funktionskopf dokumentiert, wozu die Werte die rein- und rausgehen überhaupt gut sind.
pFstKa
Wie gesagt, spontan finde ich mit dem gegebenen Code keine Unstimmigkeit, ich tippe auf den oben genannten zwei Gründen auf einen Fehler in der nicht gegebenen Implementierung von
Delphi-Quellcode:
Steuerung1.Suche_Fahrstuhl
|
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Zitat:
|
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Danke für die zügige Antwort.
Zitat:
Da ich das Ganze eher hobby-mäßig mache, beantwortet dass u.U. auch deine anderen Fragen: Zitat:
Zitat:
Zitat:
So nun aber back to topic: Zitat:
Delphi-Quellcode:
soll die Liste durchgehen und die zu suchende Instanz der Klasse Fahrstuhl in Form eines Zeigers darauf (pTFstKa) ausgeben. Es soll einerseits nach der ID und andererseits nach der Erstellungsreihenfolge gesucht werden. Letzteres brauchte ich um mit
Suche_Fahrstuhl
Delphi-Quellcode:
arbeiten zu können...So sieht die Funktion zur Zeit aus:
Combob_FstKa.ItemIndex
Delphi-Quellcode:
function Steuerung.Suche_Fahrstuhl(Suchkriterium, id_in, Stelle: cardinal):pTFstKa;
var i: integer; begin result:= pFstKa; case Suchkriterium of 1: begin //Id..... end; 2: begin i:= 1; while i < Stelle do begin result:= result^.next; i:= i + 1; end; end; end; end; Zitat:
Zitat:
Delphi-Quellcode:
durchläuft er ohne Probleme. Exception gibt es es nach wie vor bei
Steuerung1.Suche_Fahrstuhl(..)
Delphi-Quellcode:
Mir fällt übrigens noch eine potentielle Stelle ein, die den Fehler evt. hervorrufen könnte: Die hier verwendete
Form.Caption:= 'Aufzug - Nr:' + inttostr(p1^.FstKaX^.id);
Delphi-Quellcode:
wird dynamisch als eine von vielen Instanzen von TForm2 erstellt und ebenfalls einer Liste hinzugefügt...
Form
Delphi-Quellcode:
Ich werde noch ein wenig weitersuchen, damit ich meinen bisherigen Code nach Möglichkeit weiterverwenden kann. Ansonsten wäre es auch kein Problem die Aufgabenstellung mit
//Form-Listen
pForm2 = ^VForm2; VForm2 = record Form: TForm2; next: pForm2; end; ... var //global Form1: TForm1; Steuerung1: Steuerung; Fenster_FstKa: pForm2; var //lokal p,h: pForm2; Form: TForm2; ... //_____________________Form in die Formen-Liste aufnehmen_______________ //Listenelement hinzufügen p:=Fenster_FstKa; new(h); h^.next:=nil; //Objektinitialisierung: Form:= TForm2.Create(Application); h^.Form:= @Form; //an Liste anfügen if Fenster_FstKa=nil then Fenster_FstKa:=h else begin while p^.next<>nil do begin p:=p^.next; end; p^.next:=h; end;
Delphi-Quellcode:
o. Ä. zu realisieren.
TObjectList
Daher bitte ich um eine beispielhafte Lösung für: Eine beliebige Anzahl Instanzen einer Klasse (z.B. Fahrstühle) soll in eine
Delphi-Quellcode:
bzw.
TObjectList
Delphi-Quellcode:
eingetragen werden und anschließend über die Liste angesprochen werden (Property verändern, Methode aufrufen o. Ä.)
TComponentList
Vielen Dank für eure Mühen!!! :wink: |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Moin,
Ich konnte mein Problem weiter eingrenzen: Wenn ich eine Funktion zur Übergabe von Attributwerten wie folgt deklariere:
Delphi-Quellcode:
So ensteht nach wie vor die Zugriffs-Exception ganz egal ob ich
function Fahrstuhlkabine.test():integer;
begin result:=testvar; //<----Exception hier! end; ... function Steuerung.Test():cardinal; begin result:=pFstKa^.FstKaX^.test(); end; ... //Aufruf Main-Unit: test:= Steuerung1.Test(); showmessage(inttostr(test));
Delphi-Quellcode:
als private, public oder property deklariere. Wenn ich mir allerdings einen festen Wert zurückgeben lasse, ist alles super:
testvar
Delphi-Quellcode:
Die Vermutung liegt nahe, dass irgendwas mit der Attribut-Deklaration faul ist,....aber was?^^
function Fahrstuhlkabine.test():integer;
begin result:=1001 //<----keine Exception! end; ... function Steuerung.Test():cardinal; begin result:=pFstKa^.FstKaX^.test(); end; ... //Aufruf Main-Unit: test:= Steuerung1.Test(); showmessage(inttostr(test)); Für das bessere Verständnis hier die Deklaration meiner Klasse
Delphi-Quellcode:
:
Fahrstuhlkabine
Delphi-Quellcode:
Hat jemand eine Idee woran es liegen könnte? :cyclops:
FahrstuhlKabine = class
F_id: cardinal; fahrtrichtung: bool; // 1 = hoch // 0 = runter in_Benutzung: bool; Fahrtzeit: real; gewaehlteEtagen: pgewEt; speed: real; EtageV, EtageB, zulGewicht: integer; niAnEt: pNiAnEt; private F_position, F_tatsGewicht: real; public testvar:integer; property id: cardinal read F_id write F_id; property position:real read F_position write F_position; property tatsGewicht:real read F_tatsGewicht write F_tatsGewicht; constructor init(id_in:cardinal; zulGewicht_in, EtageV_in, EtageB_in: integer; sNiAnEt: string); destructor destruct(); function zielAnfahren(Ziel:integer):bool; procedure set_Zieletage(); procedure Notruf(); function lastprobe():bool; function geschwindigkeitsmessung():bool; procedure notfallbremsen(); function test():integer; end; |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Hallo-
Ich kann es mir erst heute Abend genauer anschauen, aber bzgl: Zitat:
Halte im Debugger doch mal in der Funktion an - Kannst du in deiner Fahrstuhlkabinen-Instanz überhaupt irgendwelche brauchbaren Daten wiederfinden? |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Hi,
jop, du hast Recht: Wenn ich innerhalb der
Delphi-Quellcode:
einige Attribut-Werte über den Debugger anzeigen lassen will, steht "Nicht verfügbarer Wert" da...aber warum?
function Fahrstuhlkabine.test():integer;
begin result:=testvar; //Abtastpunkt hier end; Wenn deine Vermutung mit dem Schrott-Zeiger richtig ist, fällt mir eine Stelle ein an der ein Fehler sein könnte:
Delphi-Quellcode:
Vielleicht ist die Adresszuweisung mithilfe von "@" bei Instanzen nicht funktionsfähig?
...
//Objektinitialisierung: FstKa:= Fahrstuhlkabine.Init(id_in, zulGewicht_in, EtageV_in, EtageB_in, sNiAnEt); h^.FstKaX:= @FstKa; ... Bin schon sehr gespannt auf deine ausführliche Analyse :o |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Kurze Grundlagen zu Klassen:
Klassen sind erstmal Typen und bekommen vor dem Namen ein
Delphi-Quellcode:
verpasst.
T
Der
Delphi-Quellcode:
heißt
constructor
Delphi-Quellcode:
und sollte nach Möglichkeit auch so benutzt/benannt werden.
Create
Delphi-Quellcode:
Wird eine Klassen-Instanz erzeugt (mit dem
TMyObj = class
public constructor Create; constructor Init; end; constructor TMyObj.Create; begin inherited; // irgendwas machen end; constructor TMyObj.Init; begin inherited Create; // irgendwas machen end;
Delphi-Quellcode:
) so liefert mir selbiger eine Referenz auf die Klasse (als einen Zeiger).
constructor
Ein Zeiger auf eine Klassen-Referenz-Variable liefert mir also nur den Zeiger auf den Zeiger der Klasse. Lustig, gell? (Das hört sich nicht nur komisch an, es ist auch komisch) Für die Verwaltung von Klassen-Instanzen (man spricht dabei von Objekten), also eine Liste mit Objekten, gibt es die ![]()
Delphi-Quellcode:
Das gibt auch kein Speicherleck, da
var
MyList : TObjectList; begin // Liste erzeugen ... MyList := TObjectList.Create( True ); try // ... mit ein paar Objekten füllen ... MyList.Add( TMyObj.Create ); MyList.Add( TMyObj.Create ); MyList.Add( TMyObj.Create ); finally // und wieder freigeben MyList.Free; end; end;
Delphi-Quellcode:
eine Liste erzeugt, die alle Objekte der Liste automatisch freigibt.
TObjectList.Create( True )
Somit solltest du deinen Ansatz mit dem ganzen Zeigergeraffel grundlegend über Bord werfen. ;) Zu deiner Klasse selber
Delphi-Quellcode:
TFahrtRichtung = ( frRunter, frHoch );
//FahrstuhlKabine = class TFahrstuhlKabine = class // diese Felder sind alle published ... eher unvorteilhaft // Der Zugriff sollte über Properties geregelt werden F_id: cardinal; //fahrtrichtung: bool; // 1 = hoch // 0 = runter Fahrtrichtung : TFahrtRichtung; In_Benutzung: bool; Fahrtzeit: real; gewaehlteEtagen: pgewEt; speed: real; EtageV, EtageB, zulGewicht: integer; niAnEt: pNiAnEt; private F_position, F_tatsGewicht: real; public testvar:integer; property id: cardinal read F_id write F_id; property position:real read F_position write F_position; property tatsGewicht:real read F_tatsGewicht write F_tatsGewicht; constructor init(id_in:cardinal; zulGewicht_in, EtageV_in, EtageB_in: integer; sNiAnEt: string); // !!! NEIN !!! // destructor destruct(); destructor Destroy; override; function zielAnfahren(Ziel:integer):bool; procedure set_Zieletage(); procedure Notruf(); function lastprobe():bool; function geschwindigkeitsmessung():bool; procedure notfallbremsen(); function test():integer; end; |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
Moin,
Zitat:
Delphi-Quellcode:
an dieser Stelle braucht...ist doch eher für vererbte Klassen nützlich oder täusch ich mich? Ich hab es bisher nie benutzt und auch nie vermisst...
inherited;
Zitat:
Delphi-Quellcode:
Mit dieser Änderung kann ich leider gar nichts anfangen...vermutlich dumme Frage, aber: wie setzt man da z.B. den Wert für "hoch"?
TFahrtRichtung = ( frRunter, frHoch );
... Fahrtrichtung : TFahrtRichtung; |
AW: dynamische Verwaltung von Objekten - Fahrstuhlsteuerung
z.B. so
Delphi-Quellcode:
Fahrtrichtung := frHoch;
Fahrtrichtung := frRunter; case Fahrtrichtung of frRunter : ; frHoch : ; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01: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 by Thomas Breitkreuz