Listen für Objekte mit abstakter Basisklasse iterieren



  • Hallo,

    ich versuche momentan, unter Verwendung von list aus der C++Standard-Library, das Entwurfsmuster Beobachter (engl. Observer) zu implementieren.
    Dafür brauche ich Listen mit Referenzen auf beliebige Kindklassen der abstrakten Basisklasse Observer. Darum greife ich auf das Prinzip der Polymorphie zurück (Instanzen einer Kindklasse sind auch Instanzen ihrer Basisklassen).

    Folgend mein momentaner Quellcode:

    // Observer.h
    #ifndef OBSERVER_H
    #define OBSERVER_H
    
    #include "Subject.h"
    
    using namespace std;
    
    class Observer
    {
       protected:
          Observer();
       public:
          virtual ~Observer();
          virtual void react(class Subject* subject) = 0;
    };
    
    #endif // OBSERVER_H
    
    // Subject.h
    #ifndef SUBJECT_H
    #define SUBJECT_H
    
    #include <list>
    #include "Observer.h"
    
    using namespace std;
    
    class Subject
    {
       private:
          list<class Observer*> observers;
          int value;
       protected:
          Subject();
       public:
          virtual ~Subject();
          void attach(Observer* observer);
          void detach(Observer* onserver);
          void setValue(int value);
          int getValue();
          void notify();
    };
    
    #endif // SUBJECT_H
    
    // Subject.cpp
    #include "Subject.h"
    
    void Subject::attach(Observer* observer)
    {
       observers.push_back(observer);
    }
    void Subject::detach(Observer* observer)
    {
       observers.remove(observer);
    }
    
    void Subject::setValue(int value)
    {
       this->value = value;
    }
    
    int Subject::getValue()
    {
       return this->value;
    }
    
    void Subject::notify()
    {
       list<class Observer*>::iterator it;
       for (it = observers.begin(); it != observers.end(); it++)
          it->react(this);
    }
    

    Wenn ich diesen Code kompiliere, bekomme ich folgende Fehlermeldung:

    `

    Subject.cpp:27 error: request for member 'react' in '* it.std::_List_iterator<_Tp>::operator-><Observer*>()', which is of pointer type 'Observer*' (maybe you meant to use '->' ?)|

    `

    Es scheint also so zu sein, dass die Liste bereits von sich aus immer Referenzen speichert, weshalb der Aufruf der react-Methode der Kindklasse von Observer in Zeile 27 scheitert, da der Iterator it vom Typ **Observer, statt vom Typ *Observer ist.

    Wie muss Zeile 27 in der Datei Subject.cpp aussehen, damit der Methodenaufruf funktioniert?

    Hinweis: Da die Klasse Observer abstrakt ist, bringt es nichts den Datentyp der Listenelemente von class Observer* zu class Observer zu ändern.



  • Ich denke da an
    (*it)->



  • volkard schrieb:

    Ich denke da an
    (*it)->

    Ja, das hat geholfen. Vielen Dank! 🙂

    Nur zum Verständnis: Ist das als Typumwandlung von Observer** zu Observer* zu verstehen?



  • ZaHaDum1984 schrieb:

    Nur zum Verständnis: Ist das als Typumwandlung von Observer** zu Observer* zu verstehen?

    Nö.
    in einem vector<int> sind ints und it ist ein int.
    in einem vector<Obersver
    > sind Obersver* und *it ist ein Obersver*.
    Wobei sich ein vector<Obersver*>::iterator ähnlich wie ein Observer** verhält, was ++ und * und so angeht, genau wie ein vector<int>::iterator sich fast wie ein int* anfühlt.



  • Wenn du das nicht nur zur Übung implementierst, würde ich dir zu boost signals2 raten, statt selber etwas zu bauen.



  • manni66 schrieb:

    Wenn du das nicht nur zur Übung implementierst, würde ich dir zu boost signals2 raten, statt selber etwas zu bauen.

    Das ist eine Aufgabe, die ich für mein Studium machen muss.



  • volkard schrieb:

    in einem vector<Observer*> sind Observer* und *it ist ein Observer*.

    FTFY 😉



  • Ich habe noch etwas recherchiert.

    Seit C++11 lässt sich Subject::notify() auch wie folgt schreiben.

    void Subject::notify()
    {
       for (auto observer: observers) observer->react(this);
    }
    

Log in to reply