1

I am trying to implement observer design pattern using C++ 11 smart pointers. Below is my code. The below program crashes if we try to remove the observer from the subject.

  //observer
    
    class iobserver
    {
    
    public:
        virtual void update() = 0;
    
    };
    
    
    
    using ObserverSPtr = shared_ptr<iobserver>;
    class isubject
    {
    public:  
    
        virtual void notifyall() = 0;
        virtual void attach(ObserverSPtr obserber) = 0;
        virtual void detach(ObserverSPtr obserber) = 0;
    
        virtual int&  getState() = 0;
        virtual void setState(int state) = 0;
    };
    
    
    using ObserverList = list< ObserverSPtr>;
    using SubjectSptr = shared_ptr<isubject>;
    
    
    class Subject :public isubject
    {
        int state;
        ObserverList subscribed_observers;
    
    public:
    
        Subject()
        {
            state = -1;
            subscribed_observers.clear();
        }
        void attach(ObserverSPtr observer)
        {
            subscribed_observers.push_back(observer);
        }
    
        void detach(ObserverSPtr observer)
        {
            subscribed_observers.remove(observer);
        }
    
        void notifyall()
        {
            for (auto &observer : subscribed_observers)
            {
                observer->update();
            }
        }
    
        int& getState()
        {
            return state;
        }
    
        void setState(int state)
        {
           this->state = state;
           this->notifyall();
        }
    
    };
    
    class Observer :public iobserver
    {
        weak_ptr<isubject> subject;
    public:
    
        Observer( SubjectSptr subject)
        {
            this->subject = subject;
            subject->attach(static_cast<ObserverSPtr>(this));
            
        }
        void update()
        {
            cout << "Subject got updated to new state:" << subject.lock()->getState() << endl;
        }
    };

 

Below is the driver code

    int main()
    {
        //observer
        /*
         1.subject
         2.observer
         
        
        */
    
        auto subject = make_shared<Subject>();
        auto observer1 = make_shared<Observer>(subject);
        auto observer2 = make_shared<Observer>(subject);
        auto observer3 = make_shared<Observer>(subject);
       
        subject->setState(2);
        
        
                return 0;
    }

Crash occurs when we try to detach observer3 from subject. Can anyone help me with this? How to efficiently implement observer pattern using smart pointers?

Edit:

Enabled shared this for subject but still it crashes

class Subject :public isubject, public enable_shared_from_this<Subject>
{
    int state;
    ObserverList subscribed_observers;

public:

    shared_ptr<Subject> shared_this()
    {
        return shared_from_this();
    }
    Subject()
    {
        state = -1;
        subscribed_observers.clear();
    }
    void attach(ObserverSPtr observer)
    {
        subscribed_observers.push_back(observer);
    }

    void detach(ObserverSPtr observer)
    {
        subscribed_observers.remove(observer);
    }

    void notifyall()
    {
        for (auto &observer : subscribed_observers)
        {
            observer->update();
        }
    }

    int& getState()
    {
        return state;
    }

    void setState(int state)
    {
       this->state = state;
       this->notifyall();
    }

};
Meraj Hussain
  • 329
  • 1
  • 6
  • 24
  • 3
    `static_cast(this)` is wrong. It hands ownership of `this` to a (new) group of shared pointers, which is wrong because `this` is already owned by the caller of the constructor, e.g. the shared pointer group created with `make_shared` in `main`. (The two shared pointer groups would not know about each other in this case and both delete the object.) You want [`std::enable_shared_from_this`](https://en.cppreference.com/w/cpp/memory/enable_shared_from_this) instead. – user17732522 May 07 '23 at 08:32
  • 1
    Does this answer your question? [Cast 'this' to std::shared\_ptr](https://stackoverflow.com/questions/27894246/cast-this-to-stdshared-ptr), https://stackoverflow.com/questions/36863240/how-to-return-shared-ptr-to-current-object-from-inside-the-this-object-itself, https://stackoverflow.com/questions/11711034/stdshared-ptr-of-this, etc. – user17732522 May 07 '23 at 08:35
  • I have inherited Subject from enable_shared_from_this. Still the crash occurs when detaching lass Subject :public isubject, enable_shared_from_this { int state; ObserverList subscribed_observers; public: shared_ptr shared_this() { return shared_from_this(); } – Meraj Hussain May 07 '23 at 13:22
  • Please read the links I gave carefully. `enable_shared_from_this` must be inherited _publicly_. – user17732522 May 07 '23 at 13:31
  • still it crashes. Tried using public inheritance – Meraj Hussain May 07 '23 at 14:00
  • It is also the wrong class... You are supposed to replace the `static_cast` in `Observer`, nothing in `Subject`... – user17732522 May 07 '23 at 14:17
  • yes i removed static_cast as well subject->attach(this->shared_this()); – Meraj Hussain May 07 '23 at 14:27
  • Didn't realize before that you are doing this in the constructor: You also can't use `shared_from_this` in the constructor. Instead use a `static` factory member function. See https://stackoverflow.com/questions/31924396/why-shared-from-this-cant-be-used-in-constructor-from-technical-standpoint. – user17732522 May 07 '23 at 14:33

0 Answers0