0

It's been a while since I did much with c++. I am trying to implement an the observable pattern, by passing in derived classes of an Observer class and storing them in a vector<Observer>. I know I am passing in a derived class object, because the call to the notify() method in the registerObserver() method call the derived class method. When I get the objects out of the vector and call the notify method I get the base class method.

I am pretty sure it's either (or both) the call to push_back(observer) that is creating a copy of the derived class as a base class object, or the for(Observer o : observers) { that is the cause of the problem.

Here is the code of interest:

the base class

// Observer.h
class Observer
{
  public:
     virtual void notify();
};

// Observer.cpp
void Observer::notify()
{
    Serial.println("got a notification in base class");
}

the derived class

// DatabaseUpdater.h (derived class)
class DatabaseUpdater : public Observer
{
  public:
    void notify() override;
};

// DatabaseUpdater.cpp
void DatabaseUpdater::notify()
{
    Serial.println("got a notification in database class");
}

the subject class

// HwMonitor.h (subject class)
class HwMonitor
{

  public:
    void registerObserver(Observer& observer);
    void event();

  private:
    std::vector<Observer> observers;
};

//HwMonitor.cpp
void HwMonitor::registerObserver(Observer &observer)
{
    Serial.println("adding observer");
    observer.notify();
    observers.push_back(observer);
}

void HwMonitor::event()
{
    Serial.println("event");
    for(Observer o : observers) {
        o.notify();
    }
}

the "main" (Ardunio)

//app.ino
DatabaseUpdater o;
HwMonitor esp;

void setup()
{
    Serial.begin(115200);
    delay(2000);
    Serial.println("registering observer");
    esp.registerObserver(o);
}

void loop()
{
    Serial.println("calling an event");
    esp.event();
    delay(1000);
}
user673679
  • 1,327
  • 1
  • 16
  • 35
nPn
  • 16,254
  • 9
  • 35
  • 58
  • 5
    Your vector in `HwMonitor` stores *objects*, not references or pointers which is needed for polymorphism. Please [read about *object slicing*](http://stackoverflow.com/questions/274626/what-is-object-slicing). – Some programmer dude Dec 29 '17 at 20:03
  • Look up "Curiously recurring template pattern". https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern – Jive Dadson Dec 29 '17 at 20:40
  • @Someprogrammerdude thanks, I assumed this was what was happening, but was not sure where. – nPn Dec 29 '17 at 22:59
  • @JiveDadson - interesting read, thanks – nPn Dec 29 '17 at 22:59
  • Also in the for loop in HwMonitor::event you should use a reference or 'o' will be a sliced copy of the observer – Ian4264 Dec 29 '17 at 23:29

1 Answers1

0

If you have a vector<Observer>, when you store a DerivedObserver, the vector only stores it as an Observer, slicing the object. You have to store object references (pointers) if you want to retain the derived object. And of course, that means the derived object actually has to remain alive for it to be called later.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23