本文主要介绍了c++中函数对象的基本概念,以及stl中自带的常用的函数对象(包括一元函数对象和二元的函数对象)。然后以binder1st和binder2nd为例以代码为示例,简单的使用方法。然后为了加深对函数对象的理解,自己根据类模板和函数模板编写了一个test_binder1st类模板和test_bind1st函数模板,用以实现stl中binder1st和bind1st的功能。
目录
函数对象的简介
函数对象就是重载了“()”运算符的类的对象,这样的话,对象就可以像函数一样使用。如下面的一段代码:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <memory>
#pragma warning(disable:4996)
using namespace std;
class test_add{
public:
int operator () (int a, int b)
{
return a + b;
}
};
class test_sub{
public:
int operator () (int a, int b)
{
return a - b;
}
};
int main(int argc, char *argv[])
{
int a = 10;
int b = 20;
test_add add;
test_sub sub;
cout << "a+b= " << add(a, b) << endl;
cout << "a-b= " << sub(a, b) << endl;
return 0;
}
我们在自定义的类中首先重载了“()”运算符,这样,在使用时定义两个对象add和sub,然后就可以直接向函数那样add(a,b),sub(a,b).下面是测试的结果。
a+b= 30
a-b= -10
请按任意键继续. . .
以上是自定义的类,里面重载“()”运算符。实际上stl中有现成的函数对象可供调用,如需要实现上述的功能,直接调用stl中自带的即可,如下代码片段。测试结果和上面的代码一样的。
int a = 10;
int b = 20;
minus<int> int_min;
plus<int> int_plus;
cout << "a+b= " << int_plus(a, b) << endl;
cout << "a-b= " << int_min(a, b) << endl;
c++中stl自带常用的函数对象
除了上面两个实现加减功能的函数对象,实际上stl自带了很多函数对象供大家使用。常用的如下,并附带测试结果。
#include "stdafx.h"
#include <iostream>
#include <functional>
#pragma warning(disable:4996)
using namespace std;
int main(int argc, char *argv[])
{
int a = 10;
int b = 20;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
cout << endl;
plus<int> int_plus;
cout << "a+b= " << int_plus(a, b) << endl;
minus<int> int_min;
cout << "a-b= " << int_min(a, b) << endl;
negate<int> int_neg;
cout << "-a= " << int_neg(a) << endl;
cout << "-b= " << int_neg(b) << endl;
multiplies<int> int_multi;
cout << "a*b= " << int_multi(a, b) << endl;
divides<int> int_div;
cout << "a/b = " << int_div(a, b) << endl;
cout << "b/a = " << int_div(b, a) << endl;
modulus<int> int_mod;
cout << "a%b = " << int_mod(a, b) << endl;
cout << "b/a = " << int_mod(b, a) << endl;
equal_to<int> int_equ;//if = return 1 else return 0
cout << "a!=b " << int_equ(a, b) << endl;
cout << "(b-a) = a " << int_equ(int_min(b, a), a) << endl;
not_equal_to<int> int_not_equ;//
cout << "not_equ a!=b " << int_not_equ(a, b) << endl;
cout << "not_equ (b-a) = a " << int_not_equ(int_min(b, a), a) << endl;
greater<int> int_gre;
cout << "a>b " << int_gre(a, b) << endl;
cout << "b>a " << int_gre(b, a) << endl;
greater_equal<int> int_gre_equ;//>or=
cout << "b-a = a " << int_gre_equ(int_min(b, a), a) << endl;
less<int> int_less;
cout << "less a<b " << int_less(a, b) << endl;
cout << "less b<a " << int_less(b, a) << endl;
less_equal<int> int_less_equ;//<or=
cout << "b-a = a " << int_less_equ(int_min(b, a), a) << endl;
logical_and<int> int_logical_and;
cout << "a&&b = " << int_logical_and(a, b) << endl;
logical_or<int> int_logical_or;
cout << "a||b = " << int_logical_or(a, b) << endl;
logical_not<int> int_logical_not;
cout << "!a = " << int_logical_not(a) << endl;
cout << "!0 = " << int_logical_not(0) << endl;
cout << "!-1 = " << int_logical_not(-1) << endl;
return 0;
}
binder1st ,binder2nd使用方法
基于是上面的使用,stl中还有将二元的函数对象变为一元的函数对象的函数适配器,下面的例子就是说明,函数适配器的使用方法。这种用法常见于,其中一个参数固定的,自由一个参数是变动的,那么为了安全起见,就用这种方法可以减少误操作。
#include "stdafx.h"
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#pragma warning(disable:4996)
using namespace std;
int main(int argc, char *argv[])
{
int a = 10;
int b = 20;
binder1st<plus<int>> b1st_plus = bind1st(plus<int>(), 10);
binder1st<minus<int>> b1st_minus = bind1st(minus<int>(), 10);
cout << "10+b=" << b1st_plus(b) << endl;
cout << "10-5=" << b1st_minus(5) << endl;
binder2nd<plus<int>> b2nd_plus = bind2nd(plus<int>(), 10);
binder2nd<minus<int>> b2nd_minus = bind2nd(minus<int>(), 10);
cout << "b+10=" << b2nd_plus(b) << endl;
cout << "5-10=" << b2nd_minus(5) << endl;
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
//使用count_if获得容器v1中大于或等于4的个数
int count = count_if(v1.begin(),v1.end(),bind1st(less_equal<int>(),4));
cout << "bind1st v1 >= 4 count=" << count << endl;
count = count_if(v1.begin(), v1.end(), bind2nd(greater_equal<int>(), 4));
cout << "bind2nd v1 >= 4 count=" << count << endl;
return 0;
}
自定义函数适配器的代码例子
#include "stdafx.h"
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#pragma warning(disable:4996)
using namespace std;
template<typename oper_fun, typename param>
class test_binder1st{
public:
test_binder1st(oper_fun operation, param first_param)
{
oper = operation;
first = first_param;
}
param operator ()(param second)
{
return oper(first, second);
}
private:
oper_fun oper;
param first;
};
template<typename oper_fun, typename param>
test_binder1st<oper_fun, param> test_bind1st(oper_fun operation, param first)
{
return test_binder1st<oper_fun, param>(operation, first);//调用的是上面test_binder1st的构造函数
}
int main(int argc, char *argv[])
{
int a = 10;
int b = 20;
test_binder1st<plus<int>, int> b1st_plus = test_bind1st(plus<int>(), 10);
test_binder1st<minus<int>, int> b1st_minus = test_bind1st(minus<int>(), 10);
cout << "10+b=" << b1st_plus(b) << endl;
cout << "10-5=" << b1st_minus(5) << endl;
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
//使用count_if获得容器v1中大于或等于4的个数
int count = count_if(v1.begin(),v1.end(),test_bind1st(less_equal<int>(),4));
cout << "bind1st v1 >= 4 count=" << count << endl;
return 0;
}