42

Suppose I have a function called

void funct2(int a) {

}


void funct(int a, (void)(*funct2)(int a)) {

 ;


}

what is the proper way to call this function? What do I need to setup to get it to work?

7
  • This question might help: stackoverflow.com/questions/9410/…
    – Jim
    Commented Jun 14, 2011 at 6:46
  • 1
    You have two functions, which one are you having problems calling? Note that you have hidden the function funct2 in funct by having an identically named pointer-to-function parameter so you will have to fully qualify funct2 to call it directly from inside funct.
    – CB Bailey
    Commented Jun 14, 2011 at 6:50
  • 7
    Right on, because C++ is C as we all know. Welcome to CloseOverflow. In case one uses C++11 there is good read here: stackoverflow.com/questions/16111285/… -- avoiding passing functions with pointers improves readability. Commented Jun 3, 2014 at 12:44
  • 7
    How is this a duplicate of the referenced question about C? It is possible that C++ provides (or at some point will provide) a different approach.
    – pooya13
    Commented Jan 14, 2019 at 21:01
  • 1
    @pooya13 It's not a duplicate. There are other ways to pass functions as parameters in C++ that are not possible in C (using functors, for example). Commented Nov 22, 2019 at 17:32

5 Answers 5

39

Another way to do it is using the functional library.

std::function<output (input)>

Here reads an example, where we would use funct2 inside funct:

#include <functional>
#include <iostream>

void displayMessage(int a) {
    std::cout << "Hello, your number is: " << a << '\n';
}

void printNumber(int a, std::function<void (int)> func) {
    func(a);
}

int main() {
    printNumber(42, displayMessage);
    return 0;
}

output :

Hello, your number is: 42
1
  • Can I use this syntax to pass a public method of class A to the constructor of class B and if yes, how? Commented Mar 28, 2022 at 19:36
38

Normally, for readability's sake, you use a typedef to define the custom type like so:

typedef void (* vFunctionCall)(int args);

when defining this typedef you want the returning argument type for the function prototypes you'll be pointing to, to lead the typedef identifier (in this case the void type) and the prototype arguments to follow it (in this case "int args").

When using this typedef as an argument for another function, you would define your function like so (this typedef can be used almost exactly like any other object type):

void funct(int a, vFunctionCall funct2) { ... }

and then used like a normal function, like so:

funct2(a);

So an entire code example would look like this:

typedef void (* vFunctionCall)(int args);

void funct(int a, vFunctionCall funct2)
{
   funct2(a);
}

void otherFunct(int a)
{
   printf("%i", a);
}

int main()
{
   funct(2, (vFunctionCall)otherFunct);
   return 0;
}

and would print out:

2
4
  • 11
    Since C++11, one would rather use using vFunctionCall = void (*)(int args); for better readability. Or even better, use std::function Commented Sep 15, 2017 at 8:29
  • 4
    There is no need to do any casting.
    – HAL9000
    Commented Sep 20, 2020 at 19:15
  • 1
    Since C++11 I would rather like to see std::function<> Commented Oct 4, 2020 at 10:28
  • 3
    @GoswinvonBrederlow std::function<void(int)> does much more than void (*)(int args), and is therefor harder for the platform to optimise
    – Caleth
    Commented Nov 23, 2020 at 12:37
1

The basic C++ way is using std::function, which acts like a "function type", for example the type int -> double in a functional language. It's not actually a type but a class template for which class instances can hold a callable function, but it's useful to think of it as used in places you would use a function type.

For example, this function takes int and returns double:

double halve(int x)
{
    return x / 2;
}

Now you can assign functions themselves (functions as first-class citizens):

std::function<double(int)> f = halve; // can store a lambda too

and you can pass it in as an argument type, or a return type. Ex:

double call_f(std::function<double(int)> f, int x)
{
    return f(x);
}

Another option is to use templates. The compiler will figure out the types and generate correctly typed code. See this comparison.

-1

A more elaborate and general (not abstract) example

#include <iostream>
#include <functional>
int Add(int a, int b)
{
    return a + b;
}
int Mul(int a, int b)
{
    return a * b;
}
int Power(int a, int b)
{
    while (b > 1)
    {
        a = a * a;
        b -= 1;
    }
    return a;
}
int Calculator(std::function<int(int, int)> foo, int a, int b)
{
    return foo(a, b);
}
int main()
{
    cout << std::endl
         << "Sum: " << Calculator(Add, 1, 2);
    cout << std::endl
         << "Mul: " << Calculator(Mul, 1, 2);
    cout << std::endl
         << "Power: " << Calculator(Power, 5, 2);
    return 0;
}
1
  • 1
    I feel like this doesn't add enough value compared to this answer to warrant being a separate answer.
    – starball
    Commented Sep 2, 2022 at 18:57
-3

check this

typedef void (*funct2)(int a);

void f(int a)
{
    print("some ...\n");
}

void dummy(int a, funct2 a)
{
     a(1);
}

void someOtherMehtod
{
    callback a = f;
    dummy(a)
}
1
  • That's C, not C++ Commented Aug 20, 2023 at 19:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.