0

I have read Head First Design Pattern recently. The book shows related codes in Java. However, I try to convert Java codes to C++. At Observer pattern chapter, I got stuck while converting somewhere. Related codes are follows.

class Subject{ //Publisher
public:
    virtual void registerObserver(ObserverPtr o) = 0;
    virtual void removeObserver(ObserverPtr o) = 0;
    virtual void notifyObservers() = 0;
};
using SubjectPtr = std::shared_ptr<Subject>;

Subscriber class interface:

class Observer{
public:
    virtual void update(double temp, double humidity, double pressure) = 0;
};

using ObserverPtr = std::shared_ptr<Observer>;

Display Element interface:

class DisplayElement{
public:
    virtual void display() = 0;
};

using DisplayElementPtr = std::shared_ptr<DisplayElement>;

and CurrentConditionsDisplay

class CurrentConditionsDisplay : public Observer, public DisplayElement{
    SubjectPtr m_weatherData;
    double temperature;
    double humidity;
public:
    CurrentConditionsDisplay(SubjectPtr weatherData);
    void update(double temperature, double humidity, double pressure);
    void display();

};

using CurrentConditionsDisplayPtr = std::shared_ptr<CurrentConditionsDisplay>;

My question:

At constructor of class CurrentCurrentConditionsDisplay, I would like that Publisher(Subject) registers CurrentCurrentConditionsDisplay.

//constructor
CurrentConditionsDisplay::CurrentConditionsDisplay(SubjectPtr weatherData) :
    temperature(0),
    humidity(0)
{
    m_weatherData = weatherData;

    /* How should I pass 'this' ? */
    m_weatherData->registerObserver(???????); //parameter type is ObserverPtr.

}

How should 'pointer this' is passed due to the fact that parameter type is ObserverPtr?

mrtkprc
  • 57
  • 7

1 Answers1

0

I suggest factory method, something like:

std::shared_ptr<CurrentConditionsDisplay>
MakeCurrentConditionsDisplay(SubjectPtr weatherData)
{
    auto res = std::make_shared<CurrentConditionsDisplay>(weatherData);

    weatherData->registerObserver(res);
    return res;
}

If you insist on doing it in the constructor, you might use std::enable_shared_from_this:

class CurrentConditionsDisplay :
    public std::enable_shared_from_this<CurrentConditionsDisplay>,
    public Observer,
    public DisplayElement
{
    SubjectPtr m_weatherData;
    double temperature = 0;
    double humidity = 0;
public:
    explicit CurrentConditionsDisplay(SubjectPtr weatherData) :
        m_weatherData(weatherData)
    {
        m_weatherData->registerObserver(shared_from_this());
    }

    void update(double temperature, double humidity, double pressure) override;
    void display() override;
};

std::shared_from_this cannot be called called from constructor

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • If I use second choice, there is an exception which has explanation with "terminate called after throwing an instance of 'std::bad_weak_ptr' what(): bad_weak_ptr" after program ends. – mrtkprc Oct 29 '19 at 15:54
  • Indeed, `std::shared_from_this` cannot be called called from constructor: [why-shared-from-this-cant-be-used-in-constructor](https://stackoverflow.com/questions/31924396/why-shared-from-this-cant-be-used-in-constructor-from-technical-standpoint) – Jarod42 Oct 29 '19 at 16:12
  • Alright, How can I apply first choice at my code? Is there your chance to explain factory method in order to perform it ? – mrtkprc Oct 29 '19 at 20:09