目录
函数指针
编辑
实例
函数指针作为某个函数的参数
实例
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 functionstd::function<void(int)> f_display = print_num;f_display(-9);// store a lambdastd::function<void()> f_display_42 = []() { print_num(42); };f_display_42();// store the result of a call to std::bindstd::function<void()> f_display_31337 = std::bind(print_num, 31337);f_display_31337();// store a call to a member functionstd::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 accessorstd::function<int(Foo const&)> f_num = &Foo::num_;std::cout << "num_: " << f_num(foo) << '\n';// store a call to a member function and objectusing 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 ptrstd::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);f_add_display3(3);// store a call to a function objectstd::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 overheadstd::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 callsreturn 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!"