Storing a Callback function in a Class

I have a class called Game, and at init I pass a vector of GameObjects, but I'm also trying to pass callback functions that are stored in the class to be called later in the class's main Update loop.

How can I pass callback functions (that expect arguments), store it in the class and call them else where? Here's some pseudo code of what I'm talking about:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Game {
public: 
	Game(GameObject &gameObjects){
		m_gameObjects = gameObjects;
	};

	void Update() {
		// Call Callback Functions and pass Game Objects vector and input struct
		CallbackA(m_gameObjects); 
		CallBackB(input);
	}

private:
	// Save Both Callback functions. HOW? :(
	void CallbackA(GameObject gameObjects); 
	void CallBackB(Input input);

	std::vector<GameObject> m_gameObjects;
};


// Callbacks
void callBackA(GameObject gameObjects) { /* Modify gameObjects */ }
void callBackB(Input input) { /* Handle Custom Input Logic */ }

// Main app
int main () {
	std::vector<GameObject> gameObjects;
	// Create Game and pass Game Objects...
	Game game(gameObjects, callBackA, callBackB); // But how do I pass in callback functions?
}
Last edited on
Have you looked at std::function http://www.cplusplus.com/reference/functional/function/function/ ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <string>
#include <functional>

class A
{
public:
  A() = default;
  ~A() = default;

  void BindCallback(std::function<int(int, int)> fn) {
    privateCallback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
  }

  void MakeCallback(int i, int j) {
    if (privateCallback)
      std::cout << "Output from callback: " << privateCallback(i, j) << std::endl;
  }

private:
  std::function<int(int, int)> privateCallback; //Could do a vector of them, or whatever
};

int f(int a, int b) {
  return (a + b);
}

int main()
{
  A obj;

  obj.BindCallback(f);

  obj.MakeCallback(3, 4);
  obj.MakeCallback(7, 8);

  return 0;
}


produces
Output from callback: 7
Output from callback: 15
Thanks a lot Jay, but are there any alternatives that don't require including another library?
You can do it like we do for function pointers in C.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>

class A
{
public:
  A() = default;
  ~A() = default;

  void BindOtherCallback(int(*fn)(int, int)) {
    callback = fn;
  }

  void MakeOtherCallback(int i, int j) {
    std::cout << "Ouput from callback: " << callback(i, j) << std::endl;
  }

private:

  int(*callback)(int, int);
};

int f(int a, int b) {
  return (a + b);
}

int f2(int a, int b) {
  return (a - b);
}

int main()
{
  A obj;

  obj.BindOtherCallback(f2);
  obj.MakeOtherCallback(7, 2);
  obj.MakeOtherCallback(9, -13);

  obj.BindOtherCallback(f);
  obj.MakeOtherCallback(7, 2);
  obj.MakeOtherCallback(9, -13);
}


But I highly, highly recommend you use std::function instead. Is there a particular reason why you can't include a standard library to help with it? std::function
If you use regular C-style function pointers, you can't pass member functions around and access private members inside them (and other restrictions). std::function would be ideal except in some somewhat specific circumstances.
Thanks Jay, I'll give <functional> a try. I had no reasons not too, I'm just very paranoid with compile time and try to keep the number of libraries I include to a minimum. Again, I'm probably being unnecessarily paranoid.

Thanks again Jay!
Unless your program is time-critical, you shouldn't notice a difference between the amount of time it'll take to execute your callbacks using std::function and just using c-style function pointers. Compile times will go up, but not by much.
std::function adds a lot of functionality, well worth the extra little bit of time.
> Why does std::function cause a small decrease in performance?

See http://www.cplusplus.com/forum/general/181817/#msg891546
Topic archived. No new replies allowed.