目录
函数指针
编辑
实例
函数指针作为某个函数的参数
实例
std::function轻松实现回调函数
绑定一个函数
作为回调函数
作为函数入参
函数指针
函数指针是指向函数的指针变量。
通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。
函数指针可以像一般函数一样,用于调用函数、传递参数。
函数指针类型的声明:
typedef type (*fun_ptr)(type,type); // 声明一个指向同样参数、返回值的函数指针类型
 
实例
以下实例声明了函数指针变量 p,指向函数 max:
#include <stdio.h>
#define  _CRT_SECURE_NO_WARNINGS
typedef int(*func_ptr)(int, int);
int max(int x, int y)
{
	return x > y ? x : y;
}
int main(void)
{
	//p是指向max的函数指针
	func_ptr p = &max;//也可以写成 func_ptr p = max;
	int a, b, c, d;
	printf("请输入三个数字:");
	scanf("%d %d %d", &a, &b, &c);
	/* 与直接调用函数等价,d = max(max(a, b), c) */
	d = p(p(a, b), c);
	printf("最大的数字是: %d\n", d);
	return 0;
} 

函数指针作为某个函数的参数
函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。
简单讲:回调函数是由别人的函数执行时调用你实现的函数。
以下是来自知乎作者常溪玲的解说:
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。
实例
实例中 populate_array() 函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。
实例中我们定义了回调函数 getNextRandomValue(),它返回一个随机值,它作为一个函数指针传递给 populate_array() 函数。
populate_array() 将调用 10 次回调函数,并将回调函数的返回值赋值给数组。
#include <stdlib.h>
#include <stdio.h>
void populate_array(int* array, size_t arraySize, int (*getNextValue)(void))
{
	for (size_t i = 0; i < arraySize; i++)
		array[i] = getNextValue();
}
// 获取随机值
int getNextRandomValue(void)
{
	return rand();
}
int main(void)
{
	int myarray[10];
	populate_array(myarray, 10, getNextRandomValue);//函数的名称就是函数的地址
	for (int i = 0; i < 10; i++) {
		printf("%d ", myarray[i]);
	}
	printf("\n");
	return 0;
} 

std::function轻松实现回调函数
#include <functional>
#include <iostream>
 
struct Foo
{
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_ + i << '\n'; }
    int num_;
};
 
void print_num(int i)
{
    std::cout << i << '\n';
}
 
struct PrintNum
{
    void operator()(int i) const
    {
        std::cout << i << '\n';
    }
};
 
int main()
{
    // store a free function
    std::function<void(int)> f_display = print_num;
    f_display(-9);
 
    // store a lambda
    std::function<void()> f_display_42 = []() { print_num(42); };
    f_display_42();
 
    // store the result of a call to std::bind
    std::function<void()> f_display_31337 = std::bind(print_num, 31337);
    f_display_31337();
 
    // store a call to a member function
    std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
    const Foo foo(314159);
    f_add_display(foo, 1);
    f_add_display(314159, 1);
 
    // store a call to a data member accessor
    std::function<int(Foo const&)> f_num = &Foo::num_;
    std::cout << "num_: " << f_num(foo) << '\n';
 
    // store a call to a member function and object
    using std::placeholders::_1;
    std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
    f_add_display2(2);
 
    // store a call to a member function and object ptr
    std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
    f_add_display3(3);
 
    // store a call to a function object
    std::function<void(int)> f_display_obj = PrintNum();
    f_display_obj(18);
 
    auto factorial = [](int n)
    {
        // store a lambda object to emulate "recursive lambda"; aware of extra overhead
        std::function<int(int)> fac = [&](int n) { return (n < 2) ? 1 : n * fac(n - 1); };
        // note that "auto fac = [&](int n) {...};" does not work in recursive calls
        return fac(n);
    };
    for (int i{5}; i != 8; ++i)
        std::cout << i << "! = " << factorial(i) << ";  ";
    std::cout << '\n';
} 

绑定一个函数
#include <functional>
#include <iostream>
//普通函数
void func(void)
{
	std::cout << __FUNCTION__ << std::endl;
}
//静态类成员函数
class Foo
{
public:
	static int foo_func(int a)
	{
		std::cout << __FUNCTION__ << "(" << a << ") ->:";
		return a;
	}
};
int main(void)
{
	std::function<void(void)> fr = func;
	fr();
	std::function<int(int)> fr1 = Foo::foo_func;
	std::cout << fr1(456) << std::endl;
} 

作为回调函数
#include <functional>
#include <iostream>
class A
{
std::function<void()> callback_;
public:
  A(const std::function<void()>& f) :callback_(f) {};
void notify(void)
{
    callback_();
  }
};
class Foo {
public:
void operator()(void)
{
std::cout << __FUNCTION__ << std::endl;
  }
};
int main(void)
{
  Foo foo;
A aa(foo);
  aa.notify();
} 
作为函数入参
#include <functional>
#include <iostream>
void call_when_even(int x, const std::function<void(int)>& f)
{
if (!(x & 1))
  {
    f(x);
  }
}
void output(int x)
{
std::cout << x << " ";
}
int main(void)
{
for (int i = 0; i < 10; ++i)
  {
    call_when_even(i, output);
  }
std::cout << std::endl;
} 
 
一些AI给出的回答
`std::function`是C++标准库中的一个通用、可调用、多态的函数封装器,可以用来存储任何可调用对象的引用,如函数指针、函数对象、Lambda表达式等。它的主要作用是将函数作为参数传递,实现回调函数的功能。
下面是一个简单的实例,演示了如何使用`std::function`存储一个函数,并调用它:` 
  
在这个例子中,我们定义了
#include <iostream>
#include <functional>
void print_hello() {
    std::cout << "Hello, world!" << std::endl;
}
int main() {
    std::function<void()> func = print_hello;
    func();
    return 0;
} 
一个名为`print_hello`的函数,用于打印"Hello, world!"。然后,我们创建了一个`std::function<void()>`类型的变量`func`,并将`print_hello`函数的地址赋值给`func`。最后,我们调用`func`,输出"Hello, world!"。
在C++中,`std::function`是一个通用、可调用、多态的函数封装器,可以用来存储任何可调用对象的引用,如函数指针、函数对象、Lambda表达式等。`std::function`的模板参数`T`表示存储的函数的参数类型,当`T`是一个函数指针类型时,`std::function`可以用来存储一个函数指针;当`T`是一个函数对象类型时,`std::function`可以用来存储一个函数对象;当`T`是一个Lambda表达式类型时,`std::function`可以用来存储一个Lambda表达式。
下面是一些例子:
// 存储一个接受两个int参数的函数
std::function<int(int, int)> func1;
// 存储一个接受一个int参数并返回一个int的函数
std::function<int(int)> func2;
// 存储一个不接受任何参数的函数
std::function<void()> func3;
// 存储一个Lambda表达式
std::function<int(int)> func4 = [](int x) { return x * 2; };
 
在这些例子中,`func1`和`func2`可以用来存储任何接受相应参数类型的函数,`func3`可以用来存储任何不接受任何参数的函数,`func4`可以用来存储一个接受一个int参数并返回一个int的Lambda表达式。
  
#include <iostream>
#include <functional>
class A {
public:
    A(const std::function<void()>& f) :callback_(f) {};
    void print() {
        callback_();
    }
private:
    std::function<void()> callback_;
};
int main() {
    A obj([&]() {
        std::cout << "Hello, World!" << std::endl;
    });
    obj.print();
    return 0;
}
 
在这个例子中,我们定义了一个名为A的类,它有一个构造函数,接受一个名为callback_的std::function<void()>类型的参数。我们还定义了一个名为print的方法,用于调用callback_函数。在main函数中,我们创建了一个A类的对象,并将一个Lambda表达式作为其构造函数的参数传递。然后我们调用obj的print方法,输出"Hello, World!"



















