目录
函数指针
编辑
实例
函数指针作为某个函数的参数
实例
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!"