Функции обратного вызова в C++

В C++, когда и как Вы используете функцию обратного вызова?

Править:
Я хотел бы видеть простой пример для записи функции обратного вызова.

280
задан Cœur 31 January 2019 в 21:08
поделиться

4 ответа

Существует также способ обратных вызовов на языке C: указатели функций

//Define a type for the callback signature,
//it is not necessary, but makes life easier

//Function pointer called CallbackType that takes a float
//and returns an int
typedef int (*CallbackType)(float);  


void DoWork(CallbackType callback)
{
  float variable = 0.0f;

  //Do calculations

  //Call the callback with the variable, and retrieve the
  //result
  int result = callback(variable);

  //Do something with the result
}

int SomeCallback(float variable)
{
  int result;

  //Interpret variable

  return result;
}

int main(int argc, char ** argv)
{
  //Pass in SomeCallback to the DoWork
  DoWork(&SomeCallback);
}

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

//Declaration:
typedef int (ClassName::*CallbackType)(float);

//This method performs work using an object instance
void DoWorkObject(CallbackType callback)
{
  //Class instance to invoke it through
  ClassName objectInstance;

  //Invocation
  int result = (objectInstance.*callback)(1.0f);
}

//This method performs work using an object pointer
void DoWorkPointer(CallbackType callback)
{
  //Class pointer to invoke it through
  ClassName * pointerInstance;

  //Invocation
  int result = (pointerInstance->*callback)(1.0f);
}

int main(int argc, char ** argv)
{
  //Pass in SomeCallback to the DoWork
  DoWorkObject(&ClassName::Method);
  DoWorkPointer(&ClassName::Method);
}
154
ответ дан 23 November 2019 в 02:00
поделиться

Скотт Мейерс приводит хороший пример:

class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);

class GameCharacter
{
public:
  typedef std::function<int (const GameCharacter&)> HealthCalcFunc;

  explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
  : healthFunc(hcf)
  { }

  int healthValue() const { return healthFunc(*this); }

private:
  HealthCalcFunc healthFunc;
};

Я думаю, что пример говорит само за себя .

std :: function <> - это «современный» способ написания обратных вызовов C ++.

67
ответ дан 23 November 2019 в 02:00
поделиться

Функция обратного вызова Callback - это метод, который передается в программу и вызывается в определенный момент программой, которой он передан.

Это очень полезно для создания многократно используемого программного обеспечения. Например, многие API операционной системы (такие как API Windows) активно используют обратные вызовы.

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

38
ответ дан 23 November 2019 в 02:00
поделиться

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

Редактировать на основе отзывов:

Несмотря на отрицательные отзывы, полученные этим ответом, он не является неправильным. Я постараюсь лучше объяснить, откуда я.

В C и C ++ есть все необходимое для реализации функций обратного вызова. Самый распространенный и тривиальный способ реализовать функцию обратного вызова - передать указатель функции в качестве аргумента функции.

Однако функции обратного вызова и указатели на функции не являются синонимами. Указатель на функцию - это языковой механизм, а функция обратного вызова - это семантическое понятие. Указатели на функции - не единственный способ реализовать функцию обратного вызова - вы также можете использовать функторы и даже разнообразные виртуальные функции. Обратным вызовом функции делает не механизм, используемый для идентификации и вызова функции, а контекст и семантика вызова. Сказать, что что-то является функцией обратного вызова, подразумевает большее, чем обычно, разделение между вызывающей функцией и конкретной вызываемой функцией, более слабую концептуальную связь между вызывающим и вызываемым, при этом вызывающий имеет явный контроль над тем, что вызывается. Именно это нечеткое представление о более слабой концептуальной связи и выборе функции, управляемой вызывающим пользователем, делает что-то функцией обратного вызова, а не использование указателя функции.

Например, расширение.В документации .NET для IFormatProvider говорится, что «GetFormat - это метод обратного вызова» , хотя это просто обычный интерфейсный метод. Я не думаю, что кто-то станет утверждать, что все вызовы виртуальных методов являются функциями обратного вызова. Методом обратного вызова GetFormat делает не механизм его передачи или вызова, а семантика выбора вызывающим методом метода GetFormat объекта.

Некоторые языки включают функции с явной семантикой обратного вызова, обычно связанные с событиями и обработкой событий. Например, C # имеет тип события с синтаксисом и семантикой, явно разработанными на основе концепции обратных вызовов. В Visual Basic есть предложение Handles , которое явно объявляет метод как функцию обратного вызова, абстрагируясь от концепции делегатов или указателей функций. В этих случаях семантическая концепция обратного вызова интегрирована в сам язык.

C и C ++, с другой стороны, не встраивают семантическую концепцию функций обратного вызова почти так же явно. Механизмы есть, интегрированной семантики нет. Вы можете легко реализовать функции обратного вызова, но чтобы получить что-то более сложное, включающее явную семантику обратного вызова, вы должны построить его поверх того, что предоставляет C ++, например, что Qt сделал со своими сигналами и слотами .

Вкратце, в C ++ есть все необходимое для реализации обратных вызовов, часто довольно легко и тривиально с использованием указателей на функции.Чего у него нет, так это ключевых слов и функций, семантика которых специфична для обратных вызовов, таких как raise , emit , Handles , event + = ] и т. д. Если вы пришли с языка с такими типами элементов, встроенная поддержка обратного вызова в C ++ будет казаться кастрированной.

8
ответ дан 23 November 2019 в 02:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: