Собираем
информацию
по крупицам

RSS подписка

Подпишитесь на новости сайта по RSS

Статьи - Компьютерное

Программирование на C++ и Qt

Пример функции обратного вызова на C++ / Qt
05-06-2011
19:53:54

В этой статье я кратко опишу готовое решение по вопросу о том, как в C++ / Qt написать функцию обратного вызова (callback-функцию).

 

Задача: есть некий класс Airplane (самолетик). Нужно сделать этому классу интерфейсный метод, через который можно указать, какую внешнюю функцию использовать для управления поведением самолетика. Затем надо создать объект класса Airplane, и задать ему функцию поведения.

 

Пусть метод, через который устанавливается функция поведения называется setCallbackFunc. Этот метод должен иметь всего один параметр - указатель на функцию, который он должен запомнить. Тогда интерфейс класса самолетика (h-файл) может выглядеть так:

 

class Airplane : public QObject

{

 Airplane(QObject *pobj=0);

 virtual ~Airplane();

 

 void setCallbackFunc(void (*func)(QObject *airplane,

                                   int &x,

                                   int &y));

 

 ...

 

private:

 int x;

 int y;

 

 // Указатель в котором запоминается

 // указатель на функцию поведения самолетика

 void (*callbackFunc)(QObject *airplane, int &x, int &y));
};

 

Вопрос: сколько параметров мы видим в прототипе метода setCallbackFunc? Для тех, кто слабо понимает жуткий синтаксис C++, скажу, что правильный ответ - один. Почему так, будет объяснено чуть ниже. Теперь непосредственно реализация метода, который устанавливает функцию обратного вызова:

 

void Airplane::setCallbackFunc( void (*func)(QObject *airplane,

                                             int &x,

                                             int &y) )

{

 // Эапоминается переданный указатель

 callbackFunc=func;

}

 

Для управления самолетиком будем использовать обычную функцию (хотя, вместо обычной функции можно использовать метод какого-нибудь класса).

 

Как видно из вышеприведенного кода, функция, которая должна управлять поведением самолетика, принимает указатель на объект, который ее вызвал (переменная *airplane). Можно обойтись и без этого указателя, но в дальнейшем он может пригодиться для вызова каких-то методов объекта самолетика. Так же эта функция принимает текущие координаты x и y самолетика по ссыке, чтобы функция могла эти координаты изменять.

 

Важный момент для понимания. Найдите в вышеприведенном коде конструкцию:

 

void (*func)(QObject *airplane,

             int &x,

             int &y)

 

Эта монструозная конструкция ни что иное, как указатель на функцию. Причем не на абы какую функцию, а только на ту, которая возвращает тип void и принимает три аргумента с типами QObject*, int&, int&. Имя этого указателя - func.

 

Функция управления самолетиком может выглядеть так:

 

Прототип в h-файле:

 

static void fly(QObject *airplane, int &x, int &y);

 

Обратите внимание, что прототип функции fly() описывается как static. Это важно, так как только статические функции (или методы классов) могут работать как callback-функции. Если забыть указать ключевое слово static, то в момент компиляции будет ошибка вида:

 

error: no matching function for call to ‘Airplane::setCallbackFunc(<unresolved overloaded function type>)’
candidates are: void Airplane::setCallbackFunc(void (*)(QObject*, int&, int&))

 

Реализация функции управления самолетиком:

 

void fly(QObject *airplane, int &x, int &y)

{

 ...

 x=x+y;

 y=y+1;

}

 

С такой реализацией самолетик полетит по мягкой параболе. Обратите внимание, что в реализации ключевое слово static не указывается. Это особенность синтаксиса C++: ключевое слово static нужно указывать только в прототипе.

 

Далее возникает вопрос: а как вызывать эту функцию обратного вызова? А очень просто! Предположим, что у класса Airplane есть метод update(), и в нем нужно сделать вызов нашей callback-функции. Код этого метода может выглядеть так:

 

void Airplane::update()

{

  // Вызов функции управления поведением самолетика

  // qobject_cast<QObject *>(this) - это указатель

  //                                 на текущий объект самолетика

  // x и y - текущие координаты самолетика

  callbackFunc(qobject_cast<QObject *>(this), x, y);

 

  ...

 

  redraw();

}

 

Теперь последний штрих. Создаем объект самолетика, и задаем ему функцию поведения:

 

 Airplane mig29;

 mig29.setCallbackFunc(fly);

 

Все! Если теперь постоянно вызывать метод mig29.update(), то координаты самолетика будут меняться согласно алгоритму, заданному в функции fly().

 



К списку "Компьютерное"

Поделиться этой страницей


Купить металлический штакетник евроштакетник.

Внимание!


На этом сайте разрабатывается программа MyTetra и её родственные проекты. Доступны к просмотру следующие базы знаний:

 

База Xintrea (стр. 1)

База Rarrugas (стр. 1)

База Balas

База YellowRaven

База Yurons

База Lesnik757

База Shandor

База Sirrichar

База Anatolean (стр. 1)

База Аrmagedec

База SorokinRed

База Deadelf79

База Adgaver (стр. 1)

База Pipitos1983

База Silenn (стр. 1)

База Shlyapnikova - херомантия и ригидность

База Velonski (стр. 1)

База BrokeRU (стр. 1)

База Mcold (стр. 1)

База Alensav (стр. 1)

База Alensav2 (стр. 1)

База Consp11 (стр. 1)

База Kozlov-AE (стр. 1)

База Wwwlir (стр. 1)

База Duwaz (стр. 1)

 

Требуют доработки:

 

База Tairesh

База Ivnglkv

База Kolyag87

База Andyk101

База Garik456456

База Harpokrat

База SalexIzyh

База RuDennn (Bunny-Hop)

База Manakaden

База Vitvrn

База Fanrok

База Grimar

База_Juryak

База Nicolasomsk

База Azatserikbaev

База Shut913

 

Подробности на странице MyTetra Share.

 WebHamster.Ru
 Домик любопытного хомячка
Яндекс индекс цитирования
Почтовый ящик