一、什么是function?
在C++中,std::function是一种模板类,它用于表示任意类型的函数或方法,可以作为函数参数或返回类型。std::function的提出可以用于替代函数指针,以此来降低使用回调函数的难度,它比普通函数指针更加的灵活和便利。
std::function的主要特点包括:
- 可以存储和执行任何类型的函数或方法,只要该函数或方法能够被复制(即它可以有一个副本)。
- 可以方便地对函数进行比较、拷贝、移动等操作。
- 可以通过std::bind函数或其他方式创建具有特定参数和返回类型的函数实例。
template< class R, class... Args > class function<R(Args...)>;
对于以上各个部分的解析:
R表示函数的返回类型,Args表示函数的参数列表。std::function模板类生成的类可以用来存储任何符合这些类型的函数。
一个简单的例子:
#include <iostream> #include <functional> // 定义一个简单的函数 int add(int a, int b) { return a + b; } int main() { // 创建一个std::function实例,存储add函数 std::function<int(int, int)> func = add; // 使用std::function执行add函数 int result = func(1, 2); std::cout << "Result: " << result << std::endl; return 0; }
在这个例子中,我们首先定义了一个简单的函数add,然后使用std::function创建了一个函数实例func,并将其初始化为add函数。最后,我们使用func执行add函数,并输出结果。
需要注意的是,std::function并不是C++标准库的一部分,而是C++11引入的新特性之一。因此,在使用std::function之前,需要确保你的编译器已经支持C++11或更高版本。
对以上例子进行详细的分析:function的R的定义是根据add函数的返回类型定义为int,函数的参数列表为两个int也是因为add函数的两个传参为int。
二、function使用详解
包装基本的函数(普通、仿函数、lambda)
#include<iostream> #include<functional> #include<string> #include <map> using namespace std; //普通函数 void swap_func(int& r1, int& r2) { int tmp = r1; r1 = r2; r2 = tmp; } //仿函数 struct Swap { void operator()(int& r1, int& r2) { int tmp = r1; r1 = r2; r2 = tmp; } }; int main() { int x = 0, y = 1; cout << x << " " << y << endl; //lambda auto swaplambda = [](int& r1, int& r2) { int tmp = r1; r1 = r2; r2 = tmp; }; function<void(int&, int&)> f1 = swap_func; f1(x, y); cout << x << " " << y << endl << endl; function<void(int&, int&)> f2 = Swap(); f2(x, y); cout << x << " " << y << endl << endl; function<void(int&, int&)> f3 = swaplambda; f3(x, y); cout << x << " " << y << endl << endl; map<string, function<void(int&, int&)>> cmdOP = { {"函数指针", swap_func}, {"仿函数", Swap()}, {"lambda", swaplambda}, }; cmdOP["函数指针"](x, y); cout << x << " " << y << endl << endl; cmdOP["仿函数"](x, y); cout << x << " " << y << endl << endl; cmdOP["lambda"](x, y); cout << x << " " << y << endl << endl; return 0; }
包装静态成员函数
包装静态成员函数,我们需要指定类域,然后加上&用于成员函数取地址,当然因为是静态成员函数其实可以不加&,但是为了统一,我们最好加上。
1.class Plus { public: static int plusi(int a, int b) { return a + b; } }; int main() { // 成员函数取地址,比较特殊,要加一个类域和& function<int(int, int)> f1 = &Plus::plusi; cout << f1(1, 2) << endl; return 0; }
包装普通成员函数
由于普通成员函数的包装还存在一个this,因此function中还需要传this,因此我们可以像以下的两种方式包装:一、传递指针,用指针去调用成员函数指针。二、传递对象,用对象去调用函数指针。(第二种可以理解成做了特殊处理)class Plus { public: static int plusi(int a, int b) { return a + b; } double plusd(double a, double b) { return a + b; } }; int main() { // 成员函数取地址,比较特殊,要加一个类域和& function<int(int, int)> f1 = &Plus::plusi; cout << f1(1, 2) << endl; function<double(Plus*, double, double)> f2 = &Plus::plusd; Plus ps; cout << f2(&ps, 1.1, 2.2) << endl; function<double(Plus, double, double)> f3 = &Plus::plusd; cout << f3(Plus(), 1.11, 2.22) << endl; return 0; }
三、bind使用详解
// 原型如下: template <class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args); // with return type (2) template <class Ret, class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args);
bind函数用于将一个可调用对象(如函数、lambda表达式等)与一组参数绑定,生成一个新的可调用对象。
第一个模板声明template <class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args);表示bind函数接受一个可调用对象fn和一组参数args,返回一个新的可调用对象。其中,Fn是可调用对象的类型,Args是参数的类型,...表示可变参数包。
第二个模板声明template <class Ret, class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args);表示bind函数接受一个可调用对象fn、一个返回类型Ret和一组参数args,返回一个新的可调用对象。其中,Ret是返回类型的类型,Fn是可调用对象的类型,Args是参数的类型,...表示可变参数包。
调整参数的顺序
如下我们可以用function进行bind改变函数传参的顺序,根据(placeholder::_第几个参数)来按照对应的位置调整顺序。如下:
int Sub(int a, int b) { return a - b; } int main() { function<int(int, int)> f1 = Sub; cout << f1(10, 5) << endl; // 调整参数顺序 function<int(int, int)> f2 = bind(Sub, placeholders::_2, placeholders::_1); cout << f2(10, 5) << endl; return 0; }
调整参数个数,用bind写死参数
我们也可以用function进行bind通过写死一些参数来调整参数的个数,当然我们也是需要用(placeholder::_第几个参数)来按照对应的位置调整。如下:
int Sub(int a, int b) { return a - b; } int main() { function<int(int, int)> f1 = Sub; cout << f1(10, 5) << endl; // 调整参数顺序 function<int(int, int)> f2 = bind(Sub, placeholders::_2, placeholders::_1); cout << f2(10, 5) << endl; // 调整参数个数,有些参数可以bind时写死 function<int(int)> f3 = bind(Sub, 20, placeholders::_1); cout << f3(5) << endl; return 0; }
用bind调整来包装成员函数
class Plus { public: static int plusi(int a, int b) { return a + b; } double plusd(double a, double b) { return a + b; } }; int main() { function<double(Plus*, double, double)> f2 = &Plus::plusd; Plus ps; cout << f2(&ps, 1.1, 2.2) << endl; function<double(Plus, double, double)> f3 = &Plus::plusd; cout << f3(Plus(), 1.11, 2.22) << endl; //用bind来写死Plus()从而简化代码 function<double(double, double)> f4 = bind(&Plus::plusd, Plus(), placeholders::_1, placeholders::_2); cout << f4(1.11, 2.22) << endl; return 0; }
感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!