Here is the code I am currently troubleshooting:
void CTimer::notify()
{
std::vector<IObserver*>::iterator it;
for(it=observers.begin();it!=observers.end();++it)
{
ITimerNotification* notification = new CTimerNotification(now());
(*it)->readNotification(*notification);
}
}
class CTimerNotification : public ITimerNotification
{
public:
CTimerNotification(const timeval& t)
{
time = t;
}
protected:
timeval time;
private:
virtual ~CTimerNotification();
virtual void read(const IObserver& o) const
{
o.update(*this);
}
virtual const timeval& getTime() const
{
return time;
}
};
class IObserver
{
public:
virtual ~IObserver();
virtual void readNotification(const INotification&) const=0;
virtual void update(const INotification&) const=0;
};
class ITimerObserver : public IObserver
{
public:
virtual void update(const ITimerNotification&) const=0;
};
class TestObserver : public ITimerObserver
{
public:
virtual void readNotification(const INotification& n) const
{
n.read(*this);
}
virtual void update(const INotification& n) const
{
std::cout<<"???: TestObserver: update()!\n";
}
virtual void update(const ITimerNotification& n) const
{
std::cout<< n.getTime().tv_sec << "." << n.getTime().tv_usec <<": TestObserver: update()!\n";
}
};
So the code runs, CTimer::notify()
gets called, which creates a TimerNotification
and passes it to the observer via readNotification()
which in turn calls the notification's read()
method, which finally calls the observer's (hopefully) correct update()
method.
The last step is what fails. It calls the update(INotification&)
method instead of the desired update(ITimerNotification&)
method.
What am I missing here for this attempted Double Dispatch pattern to work? It does not appear to be getting the correct type information to select the appropriate function call.
Thanks for any help!
CTimerNotification
needs a read
something like this
virtual void read(const IObserver& o) const {
ITimerObserver* to = dynamic_cast<ITimerObserver*>(&o);
if (to) {
to->update(*this);
} else {
o.update(*this);
}
}
and you need a using IObserver::update;
in ITimerObserver
.