简体   繁体   中英

Shared pointer using (this) registering to an observer

I am having a problem trying to use a shared pointer from a class that wants to register to an observer (using ) here is the example.

Observer.hpp

class Observer {
virtual void update() = 0;
}

Consumer.hpp

class Consumer : public Observer {
virtual void update() override;
}

Consumer.cpp

class Consumer {
***

THIS IS NOT WORKING - How to do it using shared pointers??


register.registerObserver(std::make_shared<Observer>(this));
}

Register.cpp

class Register {
void registerObserver(const std::shared_ptr<Observer>& observer);
}

You should never usemake_shared or otherwise construct a shared_ptr from this.

Additionally never combine memory management techniques unless you're absolutely sure you know and understand completely what you are doing.

If you really need a shared_ptr referencing the current object you should instead construct the object as a shared_ptr the first time and have the class inherit enable_shared_from_this .

After that when you need the shared pointer use shared_from_this

Since you have a this you have already constructed your object and using the direct pointer to create another shared pointer from it will result in your reference getting destroyed as soon as one of your shared_ptr references reach 0, leaving the other having a invalid reference.

Always remember that when talking about shared pointers, what you are semantically trying to convey is about the pointed-to object ownership: is it an unique ownership? Is it shared? Is it just for using the pointed-to object state?

In particular, the Observer pattern defines two interfaces. The observed subject must have some kind of reference to the observers (so it can use their callback() to update/notify them). On the other hand, the observer must have a reference to the observed subject so it can ask information when its state changes (assuming that the observer is listening for changes in the observed subject). So, these references in each object might be just weak_ptrs, because we are not interested in controlling the lifetime of the pointed-to objects.

As an example, lets say we have a data producer object (the one which is going to be observed), and a data printer object (the one observing for new data made by the producer). So, the code might look like this:

#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>

// Classes have default constructors and destructors.
class DataPrinter;

class DataProducer
{
 public:

    std::string data_{"Data"};

    void subscribeObserver(std::weak_ptr<DataPrinter> dataPrinter_ptr);
    void notifyObservers();

 private:
    std::weak_ptr<DataPrinter> dataPrinter_ptr_;
};

class DataPrinter
{
 public:

    explicit DataPrinter(std::weak_ptr<DataProducer> dataProducer);
    void update();

 private:
    std::weak_ptr<DataProducer> dataProducer_ptr_;
};

// ------------------------------------------------------------------------
// DataProducer definitions.
void DataProducer::subscribeObserver(std::weak_ptr<DataPrinter> dataPrinter_ptr)
{
    dataPrinter_ptr_ = std::move(dataPrinter_ptr);
}

void DataProducer::notifyObservers()
{
    auto dp_ptr = dataPrinter_ptr_.lock();
    if (dp_ptr) dp_ptr->update();
}

// ------------------------------------------------------------------------
// DataPrinter definitions.
DataPrinter::DataPrinter(std::weak_ptr<DataProducer> dataProducer) : dataProducer_ptr_(std::move(dataProducer))
{
    auto dp_ptr = dataProducer.lock();
    if (dp_ptr) dp_ptr->subscribeObserver(std::shared_ptr<DataPrinter>(this));
}

void DataPrinter::update()
{
    auto dp_ptr = dataProducer_ptr_.lock();
    if (dp_ptr) std::cout << dp_ptr->data_ << std::endl;
}

// ------------------------------------------------------------------------
int main()
{
    std::shared_ptr<DataProducer> dataProducer = std::make_shared<DataProducer>();
    std::shared_ptr<DataPrinter> dataPrinter = std::make_shared<DataPrinter>(dataProducer);

    dataProducer->notifyObservers();

    return EXIT_SUCCESS;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM