CJAN.LEE
CJAN.LEE

Reputation: 1118

A good way to let the callback remember some info (C++)

I used a callback in my program, and this callback will be called repeatedly, so I want to use some method to store the current info, so that he can remember where he is. I want to create a class, and use some static members to store them, but I think it is not good...I want some suggestions, thanks a lot!!

Actually, I prefer to use structure or class, and I give a simple example for my idea.

callback(parameters)
{
   A* a->setcounter(record current value);
   A* a->getcounter(get current value);
   A* a->addcounter(current value ++);
   A* a->calculate(do some calculation with values);
}

What confused me is that I should first create a object of class A, but I don't want to do this, so I choose to use static member, but I think there should be a better way.

Upvotes: 2

Views: 262

Answers (3)

jogojapan
jogojapan

Reputation: 69977

If you use a functor, i.e. an object of a class that defines an operator(), you can use that in the same way as a function (e.g. in the place of the callback function you use now), but in data members of the class you can store state information. Something along the lines of this:

class CallbackObject {
  int _state_information;
public:
  CallbackObject():_state_information(0) {}

  void operator()(int some_data_to_process) {
    /* ..process data.. */

    ++_state_information; // Update internal state
  }
};

Then objects of this class can be used in the same way as a callback function.


However, if you can use C++11, there is a particularly convenient way to achieve a similar effect, using capturing lambdas:

#include <iostream>

/* This is our "backend" that calls the callback
   function: */
template <typename Callback>
void process(int data, Callback callback) {
  callback(data);
}

int main()
{
  /* State information: */
  int num_calls = 0;

  /* Here we define the callback function as a lambda: */
  auto callback = [&num_calls](int data) { ++num_calls; };

  /* Have it called a few times: */
  for (int i = 0 ; i < 10 ; ++i)
    process(i,callback);

  std::cout << "Callback was called " << num_calls << " times." << std::endl;
  return 0;
}

The callback variable in the main function stores the lambda function. [&num_calls] means that the integer variable num_calls is captured as reference, so any change made to its value when the lambda is called will directly affect the original variable num_calls. Hence you can use captured references like num_calls (which of course may of a more complex type, or more than one variable) to store and update state information.

Upvotes: 0

Wug
Wug

Reputation: 13196

Is there some reason static variables in the function won't do it?

int my_callback(int i)
{
    static int my_int;
    if (i != -1) my_int = i;

    return my_int;
}

In this example, passing any value to my_callback will assign that value to the callback's static variable, except for -1, which will return the current value without assigning to it.

Upvotes: 0

Omaha
Omaha

Reputation: 2292

Have a parameter in your callback function be a context object, that is some instance of a struct type or class that wraps state information that is useful to the callback function to identify what the state of the program is. The callback function can predicate on this state to know what operations to perform.

Upvotes: 1

Related Questions