Q: Как сделать коллбэк, если функции принадлежат к разным классам?
A2:
В объектно-ориентированном стиле лучше всего использовать абстрактный callback-интерфейс:
Код:
class ICallback //abstract
{
public:
virtual void notify() = 0;
protected:
~ICallback() {}
};
Класс, который реализует вызов callback-функции, хранит у себя не указатель на функцию, как это обычно делается, а указатель на интерфейс ICallback:
Код:
class A
{
public:
void set_callback( ICallback* _object ) { _remote_object = _object; }
// ...
void func();
// ...
private:
ICallback* _remote_object;
};
void A::func()
{
// ...
if ( _remote_object != NULL )
_remote_object->notify();
}
Класс, нуждающийся в уведомлении от класса A, наследуется от ICallback и реализует метод notify():
Код:
class B : public ICallback
{
public:
B( A& a ) { a.set_callback( this ); }
private:
virtual void notify();
// ...
};
void B::notify()
{
// Реагируем на сообщение от класса A.
}
Преимущество такого подхода заключается в независимости интерфейса класса A от класса B. Он уже не нуждается в ссылке на класс B в callback-указателе, т.е. реализовать callback можно также в любом другом классе. Кроме того можно использовать интерфейсы с несколькими callback-функциями, а также можно добавить в callback-интерфейс указатель на свой класс для организации списка вызова.
Например:
Код:
class ICallbackInsertRemove //abstract
{
public:
virtual void inserted( unsigned disk_number ) = 0;
virtual void removed( unsigned disk_number ) = 0;
ICallbackInsertRemove* next;
protected:
ICallbackInsertRemove() : next( NULL ) {}
~ICallbackInsertRemove() {}
};
Организация вызова примерно следующая:
Код:
void A::func()
{
// ...
for ( ICallbackInsertRemove* ro = _remote_object; ro != NULL; ro = ro->next )
ro->inserted( disk ); // или, например, ro->removed( disk )
}
Ну и, разумеется, для списка нужно доработать функцию set_callback() и, возможно, добавить функцию remove_callback().