C++ 11 新特性std::function
一、 一般函数指针
函数指针,顾名思义,它就是指向函数的指针变量,该变量指向函数。
void print_num(int i)
{
std::cout << i << '\n';
}
void main()
{
//一般函数指针
typedef void(*pfunc1)(int);
pfunc1 func_1;
func_1 = print_num;
func_1(1);
return;
}
二、类成员函数指针
类成员函数指针不同于一般函数指针,因为类成员函数都隐含了一个this指针。编译器一般也不容许类成员函数赋值给一般函数指针。在指针前加入一个域限定符,并指定成员函数对应的类的实例。
class Foo {
public:
Foo(int num) : num_(num) {}
void print_add(int i) { std::cout << num_+i << '\n'; }
int num_;
};
void main()
{
//类成员函数指针
typedef void (Foo::*pfunc2)(int);
Foo foo2(2);
pfunc2 func2 = &Foo::print_add;
(foo2.*func2)(2);
return;
}
对于静态类成员函数,实际上就是一个作用域在类内部的普通函数,没有隐含的this指针。
class Foo {
public:
Foo(int num) : num_(num) {}
void print_add(int i) { std::cout << num_+i << '\n'; }
static void print_add2(int i) {
std::cout << "I am static" << '\n';
}
int num_;
};
void main()
{
func_1 = &Foo::print_add2;
func_1(2);
return;
}
三、C++ 11特性 std::function
定义
template< class R, class... Args >
class function<R(Args...)>;
std::function
实现了一套类型消除机制,可以统一处理不同的函数对象类型。以前我们使用函数指针来完成这些;现在我们可以使用更安全的std::function
来完成这些任务
- 类模板 std::function 是通用多态函数封装器。
- std::function 的实例能存储、复制及调用任何可调用 (Callable) 目标——函数、 lambda 表达式、 bind 表达式或其他函数对象,还有指向成员函数指针和指向数据成员指针。
- 它也是对 C++ 中现有的可调用实体的一种类型安全的包裹(相对来说,函数指针的调用不是类型安全的)
3.1 普通函数
void print_num(int i)
{
std::cout << i << '\n';
}
void main()
{
std::function<void(int)> f_display = print_num;
f_display(-9);
return;
}
3.2 Lambda函数
void print_num(int i)
{
std::cout << i << '\n';
}
void main()
{
std::function<void()> f_display_42 = []() { print_num(42); };
f_display_42();
return;
}
3.3 std::bind返回值
void print_num(int i)
{
std::cout << i << '\n';
}
void main()
{
std::function<void()> f_display_31337 = std::bind(print_num, 31337);
f_display_31337();
return;
}
3.4 类成员函数
class Foo {
public:
Foo(int num) : num_(num) {}
void print_add(int i) { std::cout << num_+i << '\n'; }
static void print_add2(int i) {
std::cout << "I am static" << '\n';
}
int num_;
};
void main()
{
std::function<void(Foo&, int)> f_add_display = &Foo::print_add;
Foo foo(314159);
f_add_display(foo, 1);
return;
}
3.5 类的成员变量
class Foo {
public:
Foo(int num) : num_(num) {}
void print_add(int i) { std::cout << num_+i << '\n'; }
static void print_add2(int i) {
std::cout << "I am static" << '\n';
}
int num_;
};
void main()
{
Foo foo(314159);
std::function<int(Foo &)> f_num = &Foo::num_;
std::cout << "num_: " << f_num(foo) << '\n';
return;
}
3.6 重载运算符()
class PrintNum {
public:
void operator()(int i)
{
std::cout << i << '\n';
}
};
void main()
{
std::function<void(int)> f_display_obj = PrintNum();
f_display_obj(18);
return;
}
3.7 对于重载函数的使用
因为std::function
可以用任何对象初始化,因为它的构造函数是模板化的,它与传递给std::function
的模板参数无关。因此std::function无法识别重载函数。
class Foo {
public:
Foo(int num) : num_(num) {}
void print_add(int i) { std::cout << num_+i << '\n'; }
void print_add(int i,int q) { std::cout << num_+i << '\n'; }
static void print_add2(int i) {
std::cout << "I am static" << '\n';
}
int num_;
};
void main()
{
Foo foo(314159);
using std::placeholders::_1;
std::function<void(int)> f_add_display3 = std::bind((void(Foo::*)(int))&Foo::print_add, &foo, _1 );
f_add_display3(3);
return;
}