1.简介:
functor的英文解释为something that performs a function,即其行为类似函数的东西。C++中的仿函数是通过在类中重载 () 运算符实现,使你可以像使用函数一样来创建类的对象。
2.为什么使用仿函数(functor)
使用仿函数可以使迭代和计算分离开来。因而你的functor可以应用于不同场合,在STL的算法中就大量使用了functor,下面是STL中for_each中使用functor的示例:
struct sum
{
sum(int * t):total(t){};
int * total;
void operator()(int element)
{
*total+=element;
}
};
int main()
{
int total = 0;
sum s(&total);
int arr[] = {0, 1, 2, 3, 4, 5};
std::for_each(arr, arr+6, s);
cout << total << endl; // prints total = 15;
}
for_each
template
Function for_each(InputIterator first, InputIterator last, Function fn)
{
while (first!=last) {
fn (*first);
++first;
}
return fn; // or, since C++11: return move(fn);
}
std::function是函数模板类(是一个类)。头文件 #include
std::function
是一个函数对象的包装器,std::function
的实例可以存储,复制和调用任何可调用的目标,包括:
std::function ,能存储任何符合模板参数的函数对象。换句话说,这些拥有一致参数类型、相同返回值类型(其实不必完全相同)的函数对象,可以由 std::function 统一包装起来。
样例:
#include
#include
using namespace std;
template
void fPrint(int i)
{
printf("%d\n",i);
}
int main()
{
function f = fPrint;
f(6);
return 1;
}
以前没有这个类的时候,我们在想定义一个回调函数指针,非常的麻烦。我们通常这样的定义:
1 |
|
而使用了std::function这个类的时候,我们可以这样使用,来替换函数指针。例如:
1 |
|
std::function 的实例能存储、复制及调用任何可调用 (Callable) 目标——函数、 lambda 表达式、 bind 表达式或其他函数对象,还有指向成员函数指针和指向数据成员指针。
它也是对 C++ 中现有的可调用实体的一种类型安全的包裹(相对来说,函数指针的调用不是类型安全的)
#include
#include
#include
#include
c++将boost库中的function和bind在c++11中终于纳入了标准库的体系。
可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:
1.bind 绑定普通函数 (类,见Part2 )
#include
#include
double testFound(double x, double y) { return x / y; };
int main(int argc, char* argv[])
{
auto fhalf = std::bind(testFound, std::placeholders::_1, 2);
std::cout << fhalf(10) << '\n'; // 输出为5
return 0;
}
2. cref,ref与bind结合使用
ref可以理解为传入引用
cref 则是const reference
void f(int& n1, int& n2, const int& n3)
{
std::cout << "In function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
++n1; // increments the copy of n1 stored in the function object
++n2; // increments the main()'s n2
// ++n3; // compile error
}
void test4()
{
int n1 = 1, n2 = 2, n3 = 3;
std::function bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
n1 = 10;
n2 = 11;
n3 = 12;
std::cout << "Before function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
bound_f();
std::cout << "After function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
}
Figure, Rectangle Circle 没有继承关系的类 实现多态
利用 bind 回调函数, Figure基类中注册回调函数,实现多态时再进行调用就可以了,本质上是属于bind注册回调函数。
#include
#include
#include
#include
#include
#include
#include
#define pi 3.1415926
using namespace std;
typedef function figureCallBack;
typedef function areaCallBack;
class Figure
{
public:
void setfigureFunc(figureCallBack cb1)
{
_cb1 = cb1;//注册回调函数
}
void setareaFunc(areaCallBack cb2)
{
_cb2 = cb2;//注册回调函数
}
void displayFigure()
{
_cb1();
}
double displayArea()
{
_cb2();
}
private:
figureCallBack _cb1;
areaCallBack _cb2;
};
class Rectangle
{
public:
Rectangle(int width, int length)
: _width(width), _length(length)
{
}
void displayFigure()
{
cout << "Rectangle" << endl;
}
double displayArea()
{
return _width * _length;
}
private:
int _width;
int _length;
};
class Circle{
public:
Circle(double radius)
:_radius(radius)
{
}
void displayFigure(){
cout << "Circle" << endl;
}
double displayArea(){
return pi * _radius * _radius;
}
private:
double _radius;
};
void display(Figure &f)
{
f.displayFigure();
cout << "Area = " << f.displayArea() << endl;
}
int main()
{
Rectangle rectangle(3, 4);
Circle circle(2);
Figure f;
//矩形
figureCallBack fn1 = bind(&Rectangle::displayFigure, &rectangle);
areaCallBack fn2 = bind(&Rectangle::displayArea, &rectangle);
f.setfigureFunc(fn1);
f.setareaFunc(fn2);
display(f);
//圆形
fn1 = bind(&Circle::displayFigure, circle);
fn2 = bind(&Circle::displayArea, circle);
f.setfigureFunc(fn1);
f.setareaFunc(fn2);
display(f);
return 0;
}
这个很好玩,以前一直想要的;
#include
#include
using namespace std;
struct MyStruct
{
int val;
void print()
{
cout << "this is print" << endl;
}
void printval(int i)
{
cout << "this is printval " << i << endl;
}
};
void test1()
{
MyStruct my{ 10 };
auto func1 = mem_fn(&MyStruct::print);
func1(my); //传入my是因为必须传入this指针
auto func2 = mem_fn(&MyStruct::printval);
func2(my, 2);
auto func3 = mem_fn(&MyStruct::val);
cout << func3(my) << endl;
}
int main(int argc, char* argv[])
{
test1();
return 0;
}
for_each ----6666
#include
#include
#include
#include
using namespace std;
class Data {
public:
Data(int data)
:_data(data)
{
}
void display() {
cout << _data << endl;
}
private:
int _data;
};
void test2() {
vector vec{ Data(1), Data(2), Data(3) };
for_each(vec.begin(), vec.end(), mem_fn(&Data::display));//因为本身就是在Data类的内部,所以不再需要传入this指针
}
int main(int argc, char* argv[])
{
test2();
return 0;
}
使用算法与函数结合的方法总结:
#include
#include
#include
#include
#include
using namespace std;
void display(int i)
{
cout << i << endl;
}
struct Mydisplay {
void display(int i) {
cout << i << endl;
}
bool operator()(int i) {
cout << i << endl;
return true;
}
};
void main()
{
vector vec{ 1, 2, 3, 4, 5 };
//1.使用Lambda表达式
for_each(vec.begin(), vec.end(), [](int x){cout << x << endl;});
//2.使用普通函数
for_each(vec.begin(), vec.end(), display);
//3.bind绑定普通函数
for_each(vec.begin(), vec.end(), bind(display, 1));
//4.bind绑定类成员函数
Mydisplay my;
for_each(vec.begin(), vec.end(), bind(&Mydisplay::display, my, placeholders::_1));
// 5.使用函数对象
for_each(vec.begin(), vec.end(), Mydisplay());
}
参考:
STL 仿函数(一) bind函数回调_Worthy_Wang的博客-CSDN博客