Передача производного класса в метод в качестве аргумента, который является базовым классом с умным указателем - PullRequest
0 голосов
/ 29 октября 2019

Я недавно прочитал Head First Design Pattern. В книге приведены соответствующие коды на Java. Тем не менее, я пытаюсь конвертировать Java-коды в C ++. В главе, посвященной паттернам Observer, я застрял во время конвертации. Ниже приведены соответствующие коды.

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>;

Интерфейс класса абонента:

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

using ObserverPtr = std::shared_ptr<Observer>;

Интерфейс элемента дисплея:

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

using DisplayElementPtr = std::shared_ptr<DisplayElement>;

и 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>;

Мой вопрос:

В конструкторе класса CurrentCurrentConditionsDisplay мне бы хотелось, чтобы этот Publisher (Subject) регистрировал 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.

}

Как должен передаваться «указатель» из-зафакт, что тип параметра ObserverPtr?

1 Ответ

0 голосов
/ 29 октября 2019

Я предлагаю заводской метод, что-то вроде:

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

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

Если вы настаиваете на этом в конструкторе, вы можете использовать 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 нельзя вызвать из конструктора

...