3

I want to have objects with one method which calls a function (but every object should have a different function to call). I will try to show you what I mean by showing an example:

class Human
{
    public:
        void setMyFunction(void func);  // specify which function to call
        void callMyFunction();  // Call the specified function
};

void Human::setMyFunction(void func)    // ''
{
    myFunction = func;
}

void Human::callMyFunction()    // ''
{
    myFunction();
}

void someRandomFunction()   // A random function
{
    // Some random code
}

int main()
{
    Human Lisa;     // Create Object
    Lisa.setMyFunction();   // Set the function for that object
    Lisa.callMyFunction();  // Call the function specified earlier
}

This code (obviously) doesn't work but I hope you understand what I am trying to accomplish.

MfG, TPRammus

TPRammus
  • 491
  • 1
  • 6
  • 19
  • 3
    You will want to use [std::function](http://en.cppreference.com/w/cpp/utility/functional/function). – François Andrieux Jan 05 '17 at 20:11
  • Is the signature for the function you want to pass to the class going to be the same or should it accept `int(int, int)`, `double(double)` and `void(int)` ...? – NathanOliver Jan 05 '17 at 20:11
  • You could also use a [function pointer](http://www.cprogramming.com/tutorial/function-pointers.html). – Gavin Jan 05 '17 at 20:13
  • @FrançoisAndrieux, looks like simple function pointer will do, which would be more efficient, `than std::function`. – SergeyA Jan 05 '17 at 20:15
  • @SergeyA perhaps, but `std::function` is an important tool to know about when dealing with this kind of problem, even if it's not the right one for you. – François Andrieux Jan 05 '17 at 20:17

2 Answers2

5

You might use std::function.

#include <functional>

class Human
{
    std::function<void()> mFunc;
public:
    void setMyFunction(std::function<void()> func) { mFunc = func; }
    void callMyFunction() { if (mFunc) mFunc(); }
};

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Why `std::function`? – SergeyA Jan 05 '17 at 20:15
  • 1
    To be generic and to allow capturing lambda. – Jarod42 Jan 05 '17 at 20:16
  • But does OP needs it? There is a cost associated with it. Thanks for edit, btw – SergeyA Jan 05 '17 at 20:17
  • Thank you very much this solution works. I tried this before but it didn't work because noone told me to `#include ` (which I figured out right now). – TPRammus Jan 05 '17 at 20:20
  • @SergeyA: I think it would be premature optimization. but pointer is also possible indeed. – Jarod42 Jan 05 '17 at 20:20
  • @SergeyA I refer you to [this answer](http://stackoverflow.com/a/25848890/7359094) – François Andrieux Jan 05 '17 at 20:22
  • @FrançoisAndrieux, I know the benefits of `std::function`. I am also aware of it's penalties. For example, it calls for terrible syntax with overloaded functions. – SergeyA Jan 05 '17 at 20:30
  • @Jarod42 Now the function doesn't get called and if I remove `if (mFunc)` I get an error `terminate called after throwing an instance of 'std::bad_function_call'` – TPRammus Jan 05 '17 at 21:28
  • @Jarod42 Thank you for your effort! But in [my implementation](http://ideone.com/qaSsRq) it seems to not work properly (I have two classes). **Edit:** Nevermind. I needed to return the address of the object instead of the object himself **(** `Human & getHuman() { return lisa; }` **)**. [Code Example](http://ideone.com/UFB4KJ) – TPRammus Jan 06 '17 at 17:19
4

I would suggest using a simple function pointer. Just do this:

class Human
{
    public:
        using func_t = void (*)(); 
        void setMyFunction(func_t f) {
             func = f;
        }
        void callMyFunction() {
             func();
        }
     private:
        func_t func;
};

The reasons why one might prefer function pointers to std::function are:

  • Performance. Calling std::function tends to be slower, than calling a function by pointer.
  • std::function needs truly ugly syntax when one needs to bind it to an overloaded function.

Example:

void foo();
void foo(int x = 0);

void check() {
  Human h;
  h.setMyFunction(&foo);
}

Will fail to compile.

SergeyA
  • 61,605
  • 5
  • 78
  • 137