Dynamische Objekte und Attribute |
02.12.2014, 00:15 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Dynamische Objekte und Attribute Meine Frage: Wir haben in den vergangenen Laboraufgaben einen Saugroboter modelliert. Er hat die relevanten Attribute: Ausrichtung m_Alpha Durchmesser m_Diameter=0.4 X Position m_X Y Position m_Y gefahrene Strecke m_M Aus der Ausrichtung und der Strecke konnten die Positionen X und Y errechnet werden. Dazu haben wir die Methoden setAlignment und setMovement entwickelt mit denen wir die Ausrichtung und die zurückgelegte Strecke eingeben konnten. Mit der Methode print wurde dann die Position (X/Y) sowie die Ausrichtung Alpha angezeigt. Nun sollen wir den Saugroboter visualisieren. Dazu haben wir eine graphische Java Konsole bekommen, die parallel zu Eclipse im hintergrund läuft. Um diese Konsole ansprechen zu können sollten wir eine Klasse "World.h" in unsere Header Datei inkludieren. Mit der Methode "show(m_X, m_Y, m_Alpha, m_Diameter)" veranlassen wir die Konsole einen Saugroboter an der angegebenen Stelle mit der angegebenen Ausrichtung anzuzeigen. Und jetzt fangen meine Probleme an, ich zitiere: "Ergänzen Sie nun in der Implementierung ihrer Saugroboterklasse ein Attribut "World* m_world" mit dem Initialwert NULL. Ergänzen Sie weiter die Methode "void setWorld(World* world)", die dem Attribut den übergebenen Wert zuweist." Meine Ideen: Das Asterix bedeutet doch, dass das ein Pointer ist? Also ein Pointer den ich World nenne und der auf m_World zeigt? Die Werte die ich dem Attribut übergeben will sind doch mein Ausrichtungswinkel und die Strecke, woraus dann noch x und y berechnet werden. Das müsste ich dann eventuell vorher berechnen und dann die Ergebnisse an m_World übergeben? Das sind doch mehrere Werte dh m_world müsste dann ein array sein? Im Grunde will ich die Parameter meiner Saugroboter-Klasse an die World-Klasse übergeben, damit die Konsole diese dann grafisch darstellen kann? Dafür soll ich ja die Methode "setWorld" schreiben ... wird das dann ein copy Konstruktor? Aber der kann doch nur Werte derselben Klasse kopieren ? Ich weiss nicht wie dieses Attribut "World* m_world" zu verstehen ist, deswegen hab ich auch eine Ahnung wie ich denn jetzt die Werte daran übergeben kann. |
|||||||||||||||||
|
||||||||||||||||||
02.12.2014, 08:21 | Auf diesen Beitrag antworten » | |||||||||||||||||
eulerscheZahl | Ja, es wird ein Pointer auf eine Klasse World übergeben. Wie du ein Objekt erzeugst, entnimmst du am besten der Headerdatei: wird einen Blick hinein und suche einen Konstruktor. Da siehst du dann, was für Argumente der erwartet. edit: ich glaube, ich habe es gefunden:
(von http://www.greenfoot.org/files/javadoc/greenfoot/World.html) |
|||||||||||||||||
02.12.2014, 12:32 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Vielen Dank für Deine Antwort :-) Wir sollen erst ein Objekt der Klasse World erzeugen (und es dann verwirrenderweise world nennen) und dann ein Objekt der Klasse CVacubot (So habe ich meine Saugroboterklasse gennannt). Und dann sollen wir das Objekt world der Saugroboterklasse mit der Methode setWorld bekannt machen. In der main sähe das dann so aus: int main void() { World world; CVacubot Saugroboter; Saugroboter.setWorld(); return 0; } Jetzt ist es aber so, dass wir ja die Position des Saugroboters mit den vorher geschriebenen Methoden setAlignment und setMovement bewegen können. Also ändern sich die Parameter nicht nur für die Klasse CVacubot, sondern dann ja auch für die Klasse World. Das bedeutet doch, dass mein Objekt world dynamisch sein muss? Ich werde erstmal Deinem Hinweis nachgehen und mich mit der Übergabe per Pointer beschäftigen, vielen Dank dafür :-) |
|||||||||||||||||
02.12.2014, 13:50 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Der Absatz im Skript über die Übergabe per Pointer hat mir nicht geholfen. Letztendlich steht da, dass eine Übergabe per reference grundsätzlich vorzuziehen ist, da sie das gleiche macht, aber weniger fehleranfällig ist. Mir ist einfach nicht klar, wie das Attribut "World* m_World" zu verstehen ist. Ich habe das in meiner CVacubot.h so implementiert:
Im .cpp file habe ich dann im Default Konstruktor "m_World=0" gesetzt um es wie in der Aufgabenstellung gefordert mit NULL zu initialisieren. Bisher sieht meine Methode im .cpp file so aus:
Sobald ich die Methode der Klasse World "show(...)" aufrufe stürtzt auch die .exe von meinem Programm ab :-( |
|||||||||||||||||
Anzeige | ||||||||||||||||||
|
||||||||||||||||||
02.12.2014, 16:26 | Auf diesen Beitrag antworten » | |||||||||||||||||
eulerscheZahl | In setWorld wird doch nichts angezeigt, da wird nur m_World zugewiesen, sodass dort kein nullpointer mehr steht. Du willst eine Methode eines nicht existierenden Objekts aufrufen. Die Methode show sollst du vermutlich selbst implementieren, zumindest ist sie nicht Teil von World (siehe oben verlinkte Doku). |
|||||||||||||||||
02.12.2014, 17:02 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Die World.h die wir verwenden ist eine ganz andere, als das was Du da oben verlinkt hast. Die show Methode ist dort auch gegeben:
Und wir sollen diese Methode in "setWorld" aufrufen, sowie in jeder anderen Methode die die Position des Roboters ändert. Ich bin jetzt soweit, dass ich denke, dass das Attribut "World* m_World" ein Attribut ist, dass "m_World" heisst und zur Klasse "World" gehört. Was ich immer noch nicht verstehe ist, wie ich dem Attribut m_World die Werte für m_X, m_Y, m_Alpha und m_Diameter übergebe. Ausserdem verstehe ich nicht wieso in der Methode "setWorld(World* world)" steht und nicht "setWorld(World* m_World)". |
|||||||||||||||||
02.12.2014, 17:13 | Auf diesen Beitrag antworten » | |||||||||||||||||
eulerscheZahl | Dann lass uns nicht weiter Rätselraten spielen. Gib' mir deine Informationen (wie z.B. den besagten Header), dann kann ich auch verstehen, worum genau es geht. m_World und world sind beiden Instanzen der Klasse World. Sehe ich das richtig, das besagte Anzeige mittels Kommandozeile aufgerufen wird? |
|||||||||||||||||
02.12.2014, 17:37 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Entschuldige bitte, ich dachte ich hätte alle notwendigen Informationen geliefert. Erstmal die Aufgabe:
CVacubot.h
CVacubot.cpp
main.cpp
Edit: World.h und World.cpp nach Anforderung entfernt. |
|||||||||||||||||
02.12.2014, 17:54 | Auf diesen Beitrag antworten » | |||||||||||||||||
eulerscheZahl | Zum Testen reicht es zwar immer noch nicht (es fehlt z.B. util/Socket.h), aber ich denke, ich kann mir so einen Überblick verschaffen. Den Teil brauchst du also nicht nachliefern.
Ich fasse zusammen: wir erstellen einen Zeiger auf ein World-Objekt, geben ihm den Namen positionX und zeigen auf m_X.
* wir brauchen in der Roboterklasse einer Verweis auf eine Welt * bei setWorld wird die übergebene Welt als aktuelle Welt festgelegt * wir zeigen die Welt * die 0.4 für den Durchmesser sind ein default, falls du gar nichts angibst. Das verwendet man bei der Deklaration der Funktion, nicht beim Aufruf * wenn eine Funktion void ist, kannst du dir das return am Ende schenken Und bei der URL, die du nicht posten durftest, tippe ich auf 127.0.0.1:23454 edit: in der main:
da fehlt ein Funktionsargument, nämlich eine World also
|
|||||||||||||||||
08.12.2014, 20:51 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Das Hauptproblem war, dass ich die Methode setWorl ganz am Anfang hätte aufrufen müssen, und dann erst die setAlignment und setMovement Methoden
Und natürlich wie Du auch beschrieben hast in der setWorld Methode die übergebene Welt als aktuelle Welt.
Danke für Deine Hilfe ! Man da liegt echt noch ein weiter Weg vor mir ... aber das Gefühl, wenn nach Tagen des rumfrickeln endlich alles funktioniert ist echt toll :-D |
|||||||||||||||||
08.12.2014, 20:54 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Die Aufgabe wurde mittlerweile erweitert und zwar sollen wir nun den Roboter per Eingabe steuern. Dazu ist in der Klasse World die Methode "getKey()" implementiert. Wir haben ein Aktivitätsdiagramm bekommen, nach dem wir diese methode implementieren sollen. Sieht bei mir so aus:
Läuft auch, aber ... man muss 3-4 mal dieselbe Taste drücken bis etwas passiert. Woran liegt das ? |
|||||||||||||||||
09.12.2014, 07:57 | Auf diesen Beitrag antworten » | |||||||||||||||||
eulerscheZahl | Du rufst in der Schleife 5 Mal getKey auf, liest also auch 5 Buchstaben ein (richtig wäre einer ) Wenn du die Buchstaben in der richtigen Reihenfolge drückst (z.B. up, up, left, right, up), wird überhaupt nichts passieren.
|
|||||||||||||||||
09.12.2014, 10:09 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Saugeil ! Danke Jetzt habe ich nur ein kleines Problem mit der Schleife:
Wenn ich "string key = getKey();" nicht in die Schleife packe, dann dreht sich der Roboter immer nur im Kreis. Wenn ich es in sowohl in als auch ausserhalb der Schleife stehen habe, dann funktioniert meine while Bedingung nicht mehr, ausser, ich schreibe in der while Bedingung wieder "while (get.Key() != "e")" was dann aber wieder zu mehrfachem drücken von Tasten führt. Meine Brechstangen-Lösung war jetzt eine break Bedingung. Ich habe irgendwo gelesen, dass ich dafür in die Hölle komme, zusammen mit "goto"-Usern |
|||||||||||||||||
09.12.2014, 10:18 | Auf diesen Beitrag antworten » | |||||||||||||||||
eulerscheZahl | Bei deinem code legst du 2 Variablen namens key an, die in der Schleife verdeckt dann die außerhalb. Bei while wird die äußere abgefragt, die nur einmal vor Eintritt in die Schleife befüllt wird. versuche es mal so (ungetestet):
Ich sehe break und continue jetzt nicht so kritisch. Sogar goto kann nützlich sein, wenn du bei mehreren verschachtelten Schleifen aus allen raus willst und nicht nur aus der innersten. |
|||||||||||||||||
09.12.2014, 10:23 | Auf diesen Beitrag antworten » | |||||||||||||||||
Tommy | Läuft Und zwar noch besser als vorher! Bei meiner vorherigen Lösung passierte bei der ersten Eingabe nichts. Jetzt reagiert der Roboter sofort |
|