Сallback функция класса
Автор: Игорь Спиридонов
Иногда необходимо из функции одного класса вызвать функцию обратного вызова другого, при этом не задавая жёстко тип класса, а лишь определяя интерфейс функции(поведение).
class ClassCallback { public: //Этот метод будет callback-ом int callback(int i) { return i+1; } }; class Class1 { public: //Шаблон функции - члена template <typename T> // Первый параметр - ссылка на экземпляр класса, // второй - указатель на функцию - callback int foo( T &p, int ( T::*fn)( int)) { return ( p.*fn)( 5); //Вызов функции объекта p } }; int main( ) { ClassCallback t2; Class1 t; // Вызов шаблонной функции-члена класса Class1. int i = t.foo( t2, &ClassCallback::callback); }
Нужно только помнить, что шаблонные функции - члены не могут быть виртуальными, ввиду того, что они могут не один раз конкретизироваться.
В случае применения функтора, класса к которому можно применить оператор - (), этот пример можно унифицировать и на обычные функции.
int fooCallback(int i) { return i+1; } class ClassCallback { public: //Этот оператор будет callback-ом int operator ( ) ( int i) { return i+1; } }; class Class1 { public: //Шаблон функции - члена template <typename T> // Параметр - ссылка на экземпляр класса int foo( T &p) { return p( 5); //Вызов оператора - () } }; int main( ) { ClassCallback t2; Class1 t; // Вызов шаблонной функции-члена класса Class1 int i = t.foo( t2); i = t.foo( fooCallback); }
Также можно использовать boost::function, функтор позволяющий единообразно объявлять указатели на функции и методы классов.
//Объявляем функтор с прототипом - int (int) boost::function<int (int)> f; f = &fooCallback; //Инициализируем указателем на функцию. f( 5); //Вызываем ClassCallback t; f = &ClassCallback::callback; //Инициализируем указателем на функцию класса. f( &t, 5); //В этом случе необходимо первым параметром передать указатель на объект. //В случае "чистого" функтора, вызов не отличается от вызова функции ClassCallback t; f = boost::bind( &ClassCallback::callback, t, _1); f( 5);
Теперь в классе который вызывает callback, можно избавиться от шаблонной функции - члена, но в этом случае придётся передавать объекты "чистых" классов функторов.
11 июня 2009
Комментарии [2]