почему мы должны вызывать эти функции во время выполнения, используя указатели функций.мы можем также позвонить им напрямую - PullRequest
5 голосов
/ 15 августа 2011

Прочитав немного об указателях функций и колбэках, я не понимаю основной цели этого. Мне кажется, что вместо прямого вызова функции мы используем указатель на эту функцию для ее вызова. Кто-нибудь может объяснить мне обратные вызовы и указатели на функции? Почему происходит обратный вызов, когда мы используем указатели на функции, потому что кажется, что мы просто вызываем функцию через указатель на нее, а не вызываем напрямую?

Спасибо

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

Ответы [ 4 ]

6 голосов
/ 15 августа 2011

Что такое функция Callbak?
Проще говоря, Функция обратного вызова - это функция, которая явно не вызывается программистом.Вместо этого существует некоторый механизм, который постоянно ожидает возникновения событий, и он будет вызывать выбранные функции в ответ на определенные события.
Этот механизм обычно используется, когда операция (функция) может занять много времени для выполнения и вызывающегофункция не хочет ждать завершения операции, но хочет получить информацию о результате операции.Как правило, функции обратного вызова помогают реализовать такой асинхронный механизм , в котором вызывающий регистр регистрируется, чтобы получить информацию о результате длительной обработки и непрерывных других операций в более поздний момент времени,вызывающий получает информацию о результате.

Практический пример:
Обработка событий Windows:
практически все программы Windows устанавливают цикл обработки событий,это заставляет программу реагировать на определенные события (например, нажатия кнопок, выбор флажка, получение фокуса окна) путем вызова функции.Удобно то, что программист может указать, какая функция вызывается, когда (скажем) нажимается определенная кнопка, даже если невозможно указать, когда кнопка будет нажата.Вызываемая функция называется обратным вызовом.

Исходный код Рисунок:

//warning:  Mind compiled code, intended to illustrate the mechanism    
#include <map>

typedef void (*Callback)();
std::map<int, Callback>  callback_map;

void RegisterCallback(int event, Callback function)
{
    callback_map[event] = function;
}

bool finished = false;

int GetNextEvent()
{
    static int i = 0;
    ++i;
    if (i == 5) finished = false;
}

void EventProcessor()
{
    int event;
    while (!finished)
    {
        event = GetNextEvent();
        std::map<int, Callback>::const_iterator it = callback_map.find(event);
        if (it != callback_map.end())    // if a callback is registered for event
        {
            Callback function = *it;
            if (function)   
            {
                (*function)();
            }
            else
            {
               std::cout << "No callback found\n";
            }
        }
    }
}

void Cat()
{
   std::cout << "Cat\n";
}

void Dog()
{
    std::cout << "Dog\n";
}

void Bird()
{
    std::cout << "Bird\n";
}

int main()
{
    RegisterCallBack(1, Cat);
    RegisterCallback(2, Dog);
    RegisterCallback(3, Cat);
    RegisterCallback(4, Bird);
    RegisterCallback(5, Cat);

    EventProcessor(); 
    return 0;
}

Приведенное выше выдает следующее:

Cat  
Dog   
Cat  
Bird  
Cat  

Надеюсь, это поможет!

Примечание: Это из одного из моих предыдущих ответов, здесь

4 голосов
/ 15 августа 2011

Одна очень поразительная причина того, почему нам нужны указатели на функции, заключается в том, что они позволяют нам вызывать функцию, которую автор вызывающего кода (это мы) не знает!Обратный звонок - классический пример;автор qsort() не знает и не заботится о том, как вы сравниваете элементы, она просто пишет общий алгоритм, и вы должны предоставить функцию сравнения.

Но для другого важного, широко используемого сценарияПодумайте о динамической загрузке библиотек - под этим я подразумеваю загрузку в время запуска .Когда вы пишете свою программу, вы не знаете, какие функции существуют в какой-то загруженной библиотеке во время выполнения.Вы можете прочитать текстовую строку из пользовательского ввода, а затем открыть указанную пользователем библиотеку и выполнить указанную пользователем функцию!Единственный способ ссылаться на такую ​​функцию - через указатель.

Вот простой пример;Я надеюсь, что это убедит вас, что вы не можете покончить с указателями!

typedef int (*myfp)();  // function pointer type

const char * libname = get_library_name_from_user();
const char * funname = get_function_name_from_user();

void * libhandle = dlopen(libname, RTLD_NOW);  // load the library
myfp fun = (myfp) dlsym(libhandle, funname);   // get our mystery function...

const int result = myfp();                     // ... and call the function
                                               // -- we have no idea which one!

printf("Your function \"%s:%s\" returns %i.\n", libname, funname, result);
1 голос
/ 15 августа 2011

Это также позволяет избежать конфликта имен. Если у вас есть 2 библиотеки, оба выполняют сортировку, и оба ожидают, что вы определите функцию с именем sort_criteria, которую они могут вызывать, как бы вы отсортировали 2 разных типа объектов с помощью одной и той же функции?

Это быстро усложняется после всех переключателей if и в функции sort_criteria, с помощью обратных вызовов вы можете указать свою собственную функцию (с их хорошим интерпретацией имени) для этих функций сортировки.

1 голос
/ 15 августа 2011

Это для развязки . Посмотрите на sqlite3_exec() - он принимает указатель обратного вызова, который вызывается для каждой извлеченной строки. SQLite не заботится о том, что делает ваш обратный вызов, ему нужно только знать, как его вызвать.

Теперь вам не нужно перекомпилировать SQLite каждый раз, когда изменяется ваш обратный вызов. Вы можете скомпилировать SQLite один раз, а затем просто перекомпилировать свой код и либо пересвязать статически, либо просто перезапустить и заново связать динамически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...