简体   繁体   中英

How to resolve the compilation error here - for the observer pattern in C++?

I get the following compilation error here. Why can't the derived class access another derived class method. Although the method is public. I am confused here. Please help.

/export/home/joshis1/Dropbox/Design_Patterns_UML/ObserverPattern/ObserverPatternProgram-build-desktop-Qt_4_8_4_in_PATH__System__Release/../ObserverPatternProgram/UpdateReceiver.h:43: error: no matching function for call to 'IPublisher::registerObserver(UpdateReceiver* const)'

I have a publisher class - Interface -

class ISubscriber;

/** Interface **/


class IPublisher
{

public:
   virtual void registerObserver(ISubscriber *observer) = 0;
   virtual void unregisterObserver(ISubscriber &observer) = 0;
   virtual void notifyObserver() = 0;
   virtual void setBaudRate(int newBaudRate) = 0;
   virtual void setAspectRatio(int newAspectRatio) = 0;
   virtual void setVolumeLevel(int newVolume) = 0;
};

//////////////////////////////////////

class ISubscriber;

class UpdateManager: public IPublisher
{
 private:

    QList<ISubscriber *> subscribers;
    int m_baudRate;
    int m_aspectRatio;
    int m_volumeLevel;

  public:

    UpdateManager()
    {
        qDebug()<<"Update Manager --- Server/Subject Initialized";
        subscribers.clear();

    }

    virtual void registerObserver(ISubscriber *observer)
    {
        subscribers.append(observer);
    }

    virtual void unregisterObserver(ISubscriber *observer)
    {
        int index = subscribers.indexOf(observer);
        subscribers.removeAt(index);
        qWarning()<<"Removed the subscriber Index = "<<index;
    }

    virtual void setBaudRate(int newBaudRate)
    {
        m_baudRate = newBaudRate;
        notifyObserver();

    }

    virtual void setAspectRatio(int newAspectRatio)
    {
        m_aspectRatio = newAspectRatio;
        notifyObserver();

    }

    virtual void setVolumeLevel(int newVolume)
    {
        m_volumeLevel = newVolume;
        notifyObserver();
    }


    virtual void notifyObserver()
    {
#if 0
        foreach( ISubscriber observer, subscribers )
        {
            observer.update(m_baudRate,m_aspectRatio,m_volumeLevel);
        }
 #endif
    }


};

///////////////////

I have the observer --

/** Subscriber Interface **/
class ISubsrciber
{
   public:

    virtual void update(int baudRate, int AspectRatio, int VolumeLevel) = 0;

};

class UpdateManager;
class ISubsrciber;

#include "IPublisher.h"


class UpdateReceiver: public ISubsrciber
{
 private:
    int m_baudRate;
    int m_aspectRatio;
    int m_volumeLevel;
    int m_receiverNumber;


public:
   // static int updateReceiverTracker;

 /** Update Interface of the client **/

 void update(int baudRate, int AspectRatio, int VolumeLevel)
 {
     m_baudRate = baudRate;
     m_aspectRatio = AspectRatio;
     m_volumeLevel =  VolumeLevel;

     qDebug()<<"The following client number : "<< m_receiverNumber<< " got the update ";
     qDebug()<<"The baudRate is "<<baudRate;
     qDebug()<<"The AspectRatio is"<<AspectRatio;
     qDebug()<<"The VolumeLevel is"<<VolumeLevel;


 }

 /** Constructor -- and registers with the Server or Publisher or UpdateManager **/
 UpdateReceiver(IPublisher *updateManager)
 {
   //m_receiverNumber = UpdateReceiver::updateReceiverTracker++;

    updateManager->registerObserver(this);
 }


};

Regarding the error message you have - you don't have a method (at least in this question) with the signature that your code is apparently looking for. You have:

virtual void registerObserver(ISubscriber *observer)
    {
        subscribers.append(observer);
    }

Your first file describes an ISubscriber but your second file inherits from an ISubsrciber (sic).

You have a typo in your file. Change to ISubscriber and you should have better luck!

here updateManager->registerObserver(this); you are sending it object of UpdateReceiver while it requires ISubscriber.

class

class UpdateReceiver: public ISubsrciber   // wrong 
class UpdateReceiver: public UpdateManager // right

should inherit UpdateManager not ISubsrciber?

Well I do see a few problems along your solution. Firstly you do have different forward declarations for the type ISubscriber as I stated in my earlier comment. Which results in your program not compiling.

These two wont match for sure.

virtual void registerObserver(ISubscriber *observer) {...}
class UpdateReceiver: public ISubsrciber {...}
                                 ^^^^

Secondly your notifyObserver implementation does need some rethinking as well. But since you kind of commented that code out, I'll leave this one up to you. Just remember that you're holding pointers to ISubscriber in your subscriber list when you're trying to iterate/loop over it.

Also the definition of unregisterObserver does not match your declaration.

virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void unregisterObserver(ISubscriber *observer) {...}

BUT I would consider some major refactorings for your code. In my opinion you should not mix up the Interface of the Observer pattern with your application logic.

I think your solution should look similar to this. It's not complete and does not use your QT classes tho but you should get the idea. See the demo for a runnable solution.

class ISubscriber {
public:
    virtual void update() = 0;
};

class Publisher {
    std::vector<ISubscriber*> m_observerList;
public:
    virtual void registerSubscriber(ISubscriber& observer);
    virtual void unregisterSubscriber(ISubscriber& observer);
    virtual void notifySubscribers();
};

class UpdateManager : public Publisher {
    int m_baudRate;
    int m_aspectRatio;
    int m_volumeLevel;
public:
    virtual void setBaudRate(int newBaudRate);
    virtual void setAspectRatio(int newAspectRatio);
    virtual void setVolumeLevel(int newVolume);

    int getBaudRate() const;
    int getAspectRatio() const;
    int getVolumeLevel() const;
};

class UpdateReceiver : public ISubscriber {
    UpdateManager& m_manager;
public:
    UpdateReceiver(UpdateManager& manager) : m_manager(manager) {
        m_manager.registerSubscriber(*this);
    }
    virtual void update() {
        // Process the new values
        m_manager.getBaudRate();
        m_manager.getAspectRatio();
        m_manager.getVolumeLevel();
    }
};

DEMO

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