函数指针
主要有以下两类:
- 一般函数指针(普通函数指针 and static 成员函数指针)
- 非static成员函数指针
一般函数指针
初始化
普通函数指针
func_type func = function_name;
or
func_type func = &function_name;
static 成员函数指针
func_type func = ClassName::function_name;
or
func_type func = &ClassName::function_name;
调用
function_name(arg);
or
(*function_name)(arg);
注:同数组名类似,对函数名而言 functin_name 和 &function_name 是一样的,即地址相同,所以,上述的两种写法都可以
对于类的非static成员函数指针
初始化
func_type func = &function_name;
调用
(obj.*func)(arg);
即,非static成员函数在初始化时,必须以&的方式避免歧义,否则编译会报错为 invalid use of non-static member function
函数对象
C++推荐使用函数对象(仿函数)来替代函数指针,这样可以避免指针操作带来的繁琐,切可以维护数据,使函数带有自己的状态
函数对象主要通过重载operator()来实现,例如:
1
2
3
4
5
6
7
8
9
10
11
12
|
struct Max
{
Max() : times()
{
}
int operator()(int a, int b)
{
std::cout << "Called " << ++times << " times match" << std::endl;
return a > b ? a : b;
}
int times;
};
|
同时我们可以声明一个函数对象
1
2
3
4
5
6
|
Max max;
std::function<int(int, int)> func = max; //拷贝
max(1,3);
func(1, 3);
func = std::ref(max); //引用该对象
func(1, 3);
|
output:
1
2
3
|
Called 1 times match
Called 1 times match
Called 2 times match
|
std::bind
用于绑定函数参数,返回函数对象
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class Test
{
public:
void print()
{
std::cout << ++value << std::endl;
}
void addX(int x);
{
value += x;
std::cout << value << std::endl;
}
private:
int value;
}
Test test;
std::function<void()> func = std::bind(&Test::print, test); //test 传值
test.print(); // value is 1
func(); // value is 1
func = std::bind(&Test::print, &test); //传引用
func(); // value is 2
test.print(); // value is 3
func = std::bind(&Test::addX, &test, 5); //多参数绑定
func(); // value is 8
test.print(); // value is 9
std::function<void(int)> func1;
func1 = std::bind(&Test::addX, &test, std::placeholders::_1); //参数占位
func1(4); // value is 13
test.print(); // value is 14
|
原理描述
bind普通函数
bind成员函数,如果绑定的是*this
, 则内部调用时为(v1.*fn)()
显式传递this
占位预留参数
相关参考&援引
- 函数指针
- 函数对象
- "&" in ordinary functions pointer
- 《bind illustrated》 — Christopher M. Kohlhoff