Beziehung zwischen Klassen



  • Hallo,

    ich habe ein Problem damit Beziehungen zwischen Klassen zu realisieren. Habe das in der Vorlesung nicht richtig verstanden.

    Ich habe die Klassen
    Auto, Scanner, Autopilot.

    1 Auto hat einen Scanner
    1 Scanner ist in einem Auto eingebaut

    1 Auto hat einen Autopiloten
    1 Autopilot lenkt ein Auto

    1 Autopilot erteilt seinem Scanner einen Scanauftrag
    1 Scanner liefert Scanergebnis dem Autopiloten zurück

    Bisher habe ich es so versucht:

    In meiner Klasse Auto habe ich einen Zeiger auf ein Scanner und Autopilot
    also Scanner *pSc und Autopilot *pAp

    In meinem Autopiloten habe ich einen Zeiger auf ein Auto und einen Scanner

    Im Scanner habe ich noch nichts.

    Ist das so korrekt, oder wie funktioniert das richtig?

    Ich muss desweiteren auch mehrere Autos in einer Schleife ansprechen und bewegen. Die Autos werden vorher in einem Vektor gespeichert. Wie kann ich es so realisieren, dass ich nicht immer auto1.machwas, auto2.machwas, auto3.machwas aufrufen muss? Kann man einfach den Zeiger vom autopiloten auf das Auto immer auf das nächste Objekt zeigen lassen?



  • Ich denke, dass du das grundsätzlich verstanden hast. Hat-ein ist in der Regel eine Aggregation. (Sprich die Klasse enthält ein/mehrere Instanzen des Objektes).
    Nun ist Design nicht immer einfach und es gibt auch nicht die "wahre" Lösung.
    Aber man könnte es in etwa so machen:

    class Scanner 
    {
    };
    
    class AutoPilot 
    {
    ...
    Scanner HeatScanner; //Ein AutoPilot hat immer diese Scanner zur Verfügung
    Scanner MoveScanner; //Können auch mehrere sein
    };
    
    class Auto
    {
    ...
    AutoPilot* pilot; //Ein Auto kann kann einen AutoPilot haben, oder nicht
    };
    

    Ich habe da jetzt extra den AutoPilot als Zeiger genommen, da man da elegant den "nicht-vorhanden" Faktor reinbringen kann. Nämlich, wenn pilot 0 ist, dann hat das Auto keinen AutoPiloten zur Verfügung, anderseits zeigt der Zeiger auf ein gültiges Objekt. (Anstatt den Speicher dann roh zu verwalten, würde ich hier den Einsatz eines smart Pointern, wie z.B std::auto_ptr empfehlen, allenfalls auch einen aus boost).

    Wie ich allerdings aus deiner 2 Frage entnehme, bist du noch nicht wirklich weit fortgeschritten, was den Umgang mit C++ anbelangt, da du etwas wesentliches offensichtlich noch nicht kennst. Arrays. (Obwohl du vector ansprichst.. ich bin verwirrt. ;))

    Auto autos[100]; //100 Autos, die du bequem über eine Schleife verwalten kannst
    

    oder mit std::vector:

    std::vector<Auto> autos; // noch keine Elemente enthalten. Musst du zuerst hinzufügen. (oder per c-tor angeben).
    
    std::vector<Auto*> autos_p; //Zeiger auf Autos, musst du auch zuerst einfügen
    

    Aber auch hier wären wieder smart-Pointer angebracht und in Verbindung mit boost könntest du das relativ sauber auch mit Zeiger verwalten.
    (dir würde ich aber einfach mal die normale Variante, ohne Zeiger empfehlen, da bist du auf der sicheren Seite. ;))

    Kann man einfach den Zeiger vom autopiloten auf das Auto immer auf das nächste Objekt zeigen lassen?

    Und hier sprichst du eine Liste an. 😉

    std::list<Auto> auto_list;//ein weiterer Container aus der Standardbibliothek..
    

    Kann es sein, dass du schon sehr viel gehört hast, aber noch nicht wirklich viel selber programmier hast? 🙂



  • Danke schonmal für die ausführliche Antwort.

    Natürlich kenne ich Arrays, aber wir haben uns soweit auf einen Vektor für die Speicherung der Autos geeinigt, ich kann diese natürlich auch in einem Array speichern, was ich nun auch mal gemacht habe.

    Wo ich nun ein Problem noch habe:

    Ich kann zwar nun nacheinander über die Schleife die Autos aufrufen und dazu bringen den Autopiloten zu benutzen, allerdings hänge ich an der Stelle dann fest, wie genau ich dem Autopiloten dann sage welches Auto er zu benutzen hat 😞

    Er "lenkt" dann immer nur das erste Auto, die anderen Autos fahren einfach nur geradeaus.



  • Aso. Ja, bevorzuge ruhig vector vor normalen Arrays. War mir nur nicht sicher, ob wir auch vom gleichen sprechen.. 😉

    Bei deinem weiteren Problem komme ich jetzt nicht ganz draus.
    Du hast ja nur einen Autopiloten pro Auto. Somit "weiss" jedes Auto, welchen Autopiloten er hat. Der Autopilot im Gegenzug muss gar nicht wissen, von welchem Auto er genutzt wird.

    Demonstrier dein Problem bitte mit ein wenig (möglichst relevanten) Code.



  • Ok, dann lege ich doch mal los 🙂

    Als erstes erstelle ich dynamische Autos in der Manager.cpp

    FC *fc, *fc2;
    

    danach überprüfe ich ob die Parzelle frei ist

    if(w.getID(Location(30,2)) != Ikon('#'))
      {
        fc = new FC(ID('A'), Location(30,2), N);
    	fcs[0] = fc; 
      }
      if(w.getID(Location(20,2)) != Ikon('#'))
      {
        fc2 = new FC(ID('B'), Location(20,2), N);
    	fcs[1] = fc2; 
      }
    

    FC ist das Auto(FutureCar) und bekommt als Parameter den Namen, die Location(den Platz in der Welt) sowie die Richtung in die es am Anfang fährt.
    Desweiteren wird es in den Vektor gepusht.

    Danach rufe ich in einer Endlosschleife

    while(true)
      {
    	Sleep(100);
    	for(int i=0; i<ManageFC.size();; i++)
    	{
    	  ManageFC.at(i)->go();
    	}
      }
    

    auf.

    GO ist eine Methode des Autos, welche wiederum eine Methode step() aufruft.
    In der Methode step werden die Regeln überprüft und das Auto dann bewegt.

    void FC::step()
    {
    pilot->cruise();
    .
    .
    

    Wie man sieht, wird hier der Autopilot aufgerufen mit der Methode cruise();

    cruise sieht so aus:

    void Autopilot::cruise()
    {
      checkForPossibleActions();
      decideAboutNextAction();
      obeyTrafficRules();
      checkNewDirForTrafficJam();
      moveFC();
    }
    

    Bis hierher scheint auch noch wirklich alles zu klappen. Nun wirds kritisch.

    Ich muss in einem dynamischen Array(selbstgeschrieben) alle möglichen Fahrtmöglichkeiten speichern und dann zufällig eine davon auswählen.

    void Autopilot::checkForPossibleActions()
    {
      possibleActions.clear();
      if(scan.scanForID(7, fcs.getDir(), fcs.getLocation()).attribute == TRAVERSABLE)
        { possibleActions.push_back(GOAHEAD);}
    .
    .
    

    ScanForID bekommt als Parameter (Parzelle, Autorichtung, Autolocation)
    possibleActions.clear() soll aufgerufen werden, falls noch irgendwas in dem dynamischen Array steht. Allerdings bricht das Programm exakt an dieser Stelle mittlerweile schon ab.

    In der Klasse Autopilot habe ich

    Scanner scan;
    FC fcs;

    Ich hoffe, dass ich es verständlich rübergebracht habe.

    ---------------
    edit: dynarray.clear() und push_back klappen wieder, habe ausversehen eine Zeile auskommentiert :D.

    Funktionieren tut es aber scheinbar mir fcs.xxx nicht



  • Hmm. Das ist jetzt so sehr schwer zu sagen, an was das es liegt.
    Versuch dich mal mit dem Debugger und schau, WARUM er abbricht. (Ev. bekommst du da ja auch eine Meldung dazu.)


Anmelden zum Antworten