Ранее я опубликовал вопрос о том, как привести функцию-член к указателю функции typedef ( Как использовать указатель функции typedef для регистрации обратного вызова ), и это побудило меня рассмотреть слегка измененное решение: реализация "классического" паттерна наблюдателя.
Я хочу разрешить классу A
уведомлять наблюдателей, которые получают обратный вызов через указатель функции, и наблюдателей, которые получают обратный вызов через функцию-член, но я не могу понять, как правильно это сделать. Я просмотрел других примеров в сети и теперь я просто запутался в том, где я ошибаюсь.
Вот пример, совместимый с sscce, который я вставил на ideone.com (с ошибками компилятора под ним):
#include <set>
typedef int (*CallbackEvent)(const char*, const char*, int);
// Observer interface
class IObserver
{
public:
virtual ~IObserver(){}
virtual int CallMeBack(const char*, const char*, int);
};
class A
{
private:
std::set<IObserver> observers;
public:
A(){}
~A(){}
void RegisterObserver(const IObserver& observer)
{
observers.insert(observer);
}
inline void UnregisterObserver(const IObserver& observer)
{
observers.erase(observer);
}
void NotifyAll()
{
for(std::set<IObserver>::iterator itr = observers.begin(); itr != observers.end(); itr++)
{
int z = 3;
itr->CallMeBack("x","y",z); // <-- This is the part that's not working
}
}
};
// Has internal logic to handle the callback
class B : public IObserver
{
private:
A myA;
public:
B(A& a)
{
myA = a;
myA .RegisterObserver(*this);
}
~B()
{
myA .UnregisterObserver(*this);
}
int CallMeBack(const char* x, const char* y, int z)
{
return 0;
}
};
Ошибки компилятора:
prog.cpp: In member function ‘void A::NotifyAll()’:
prog.cpp:38: error: passing ‘const IObserver’ as ‘this’ argument of ‘virtual int IObserver::CallMeBack(const char*, const char*, int)’ discards qualifiers
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = IObserver]’:
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_tree.h:1141: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = IObserver, _Val = IObserver, _KeyOfValue = std::_Identity<IObserver>, _Compare = std::less<IObserver>, _Alloc = std::allocator<IObserver>]’
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_set.h:381: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = IObserver, _Compare = std::less<IObserver>, _Alloc = std::allocator<IObserver>]’
prog.cpp:25: instantiated from here
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’
Обратите внимание, что я делаю большую часть своего программирования на C #, так что извините за мое невежество, когда дело доходит до "нюансов" C ++. Может кто-нибудь помочь мне понять, как правильно это осуществить?
Обновление
Изменил мой код на основе ответа Наваза, вот обновленный код: http://www.ideone.com/AH3KG