oo-frage: waffe<->spieler



  • class weapon
    {
    };
    
    class character
    {
    };
    

    Der Character soll jetzt die Waffe "anlegen" können und benutzen können.

    Fragen:
    - Speichert der Character ein Zeiger auf seine Waffe oder die Waffe einen Zeiger auf seinen Träger? Oder beides? Wenn beide Zeiger aufeinander speichern kommt man als benutzer ziemlich stark durcheinander.
    - Bei einem guten Design müsste es nicht nötig sein, dass beide Zeiger aufeinander tragen, oder? Wie sehr ihr das?
    - ein Null-Pointer bedeutet keine Waffe angelegt - oder lieber doch ein zusätz. boolean dafür nehmen?
    - Nehmen wir an ein Schwer gibt dem Character zusätzlich +4 Stärke, wie wird das am sichersten implementiert? (vielleicht sogar ein Object, bei dessen Konstruktion der Bonus addiert, und bei dessen Destruktor der Bonus wieder subtrahiert wird? So eine art weapon_character_connection-Klasse.)

    Ich bin über _jede_ ernsthafte Idee bzw. Vorschlag dankbar 🙂

    Danke, fraggi



  • Naja, der Spieler _benutzt_ doch die Waffe. Also legst du sie als verschachtelte Klasse innerhalb der Charakter-Klasse an. Stichwort "Delegation" 😉



  • nun, es gibt auch waffen, die sich ihren träger suchen

    excalibur zB



  • Ich würds so lösen:

    class IItemModifierStrength
    { 
       virtual void setStrengthMod(bonus) = 0;
       virtual void getStrengthMod() = 0;
    };
    
    class ICanCarryWeapon
    {
       virtual void attachWeapon() = 0;
       virtual void detachWeapon() = 0;  
    };
    
    // danke für die vorlage crashterpiece  btw :P
    class Excalibur : public IItemModifierStrength
    {
       // pure virtual Methode muss implementiert werden
       void setStrengthMod(){}
       void getStrengthMod(){return foobar;}
    };
    
    class Player : public ICanCarryWeapon
    {
       void attachWeapon(){}
       void detachWeapon(){} 
    };
    

    Das Interface IItemModifierStrength übernimmt eben halt die Höhe des Attributs.
    Und wenn du eben die Attribute prüfst, kannst du dich auch explizit auf dieses Interface beschränken.
    Das Interface ICanCarryWeapon sorgt jetzt dafür, dass beim an- und ablegen die Werte richtig modifiziert werden.
    Wäre ne Lösung, es gibt sicher noch andere.
    rya.



  • Hallo Fraggi,

    es ist grundsätzlich zu vermeiden, dass sich zwei Klassen gegenseitig kennen - also Zeiger auf Objekte der jeweils anderen Klassen tragen.
    In welche Richtung die Beziehung implementiert wird, hängt ausschließlich davon ab, wozu die Beziehung benutzt wird. In diesem Fall würde ich vermuten, dass 'character hat weapon' die bessere Alternative ist.
    Für die Realisierung gibt es einen ganzen Sack Möglichkeiten.
    1.) einfacher Zeiger

    class weapon {};
    class character
    {
        weapon* m_weapon;
    };
    

    Nachteil: Du musst Dich im Copy-Konstruktor, Assignment-Operator und Destruktor um diesen Zeiger 'kümmern'.

    2.) Smart-Pointer

    class character
    {
        std::auto_ptr< weapon > m_weapon;
    };
    

    Damit entfällt das 'kümmmern' aber der Character ist nicht mehr kopierbar - eventuell willst Du das sogar, weil er so eine 'feste Identität' bekommt - d.h. Zeiger auf ihn bleiben gültig solange er nicht gelöscht wird.

    3.) Mehrer weapon

    class character
    {
        std::vector< weapon > m_weapons;
    };
    

    So kann der Character mehr als eine Waffe tragen. Und wenn der Container leer ist (Methode empty()) so hat er keine.
    Jede weapon kann so eine Methode Stärke besitzen und diese können in einer Methode getStaerke des characters alle summiert werden.

    Die Lösung mit dem boolean würde ich nicht machen, wenn überhaupt dann nur als Attribut von weapon - also es gibt dann eine Waffe von der Art 'keine Waffe'.

    Das mit der 'weapon_character_connection-Klasse' musst Du nochmal ausführlicher erklären, wie Du das meinst.

    Gruß
    Werner


Anmelden zum Antworten