首先,朋友们先了解下函数对象的知识
1、函数对象(function object)也称为仿函数(functor)
2、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。
3、任何重载了调用运算符operator()的类的对象都满足函数对象的特征
函数象可以把它称之为smart function。STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。
STL中提供了一元和二元函数的两种Functor,通过unary_function和binary_function提供了这两种不同参数数量的 Functor的基本结构,在这两个类型中,分别内嵌定义一元和二元函数操作在模版推演的时候需要用到的typedef.
//一元函数的定义为
template<class _A, class _R>
struct unary_function {
typedef _A argument_type;
typedef _R result_type;
};
//二元函数的定义为
template<class _A1, class _A2, class _R>
struct binary_function {
typedef _A1 first_argument_type;
typedef _A2 second_argument_type;
typedef _R result_type;
};
自定义函数对象:
#include <iostream>
using namespace std;
class CFunObj{
public:
void operator()(){
cout<<"hello,function object!"<<endl;
}
};
int main(){
CFunObj fo;
fo();
CFunObj()();
return 0;
}
函数对象与容器:
//============================================================================
// Name : Functiondemo.cpp
// Author : zfs
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
using namespace std;
#include <map>
int main()
{
map<int,string,greater<int> > testMap;
testMap.insert(map<int,string>::value_type(1,"1"));
testMap.insert(map<int,string>::value_type(3,"3"));
testMap.insert(map<int,string>::value_type(2,"2"));
testMap.insert(map<int,string>::value_type(4,"4"));
map<int,string,greater<int> >::iterator it;
for(it=testMap.begin();it!=testMap.end();++it)
{
cout<<"first:"<<(*it).first<<endl;
}
return 0;
}
函数对象与算法
/*
* 02.cpp
*
* Created on: Jun 30, 2014
* Author: zfs
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
void print(int n)
{
cout<<"n:==========="<<n<<endl;
}
int main()
{
int a[]={1,2,3,4,5};
vector<int> ve(a,a+5);
for_each(ve.begin(),ve.end(),print);
cout<<endl;
return 0;
}
STL中内置的函数对象:分为断言函数对象和算术操作函数对象
函数适配器能够将仿函数和另一个仿函数(或某个值、或某个一般函数)结合起来。
作用就是使函数转化为函数对象,或是将多参数的函数对象转化为少参数的函数对象。
标准库提供了一组函数适配器(function adapter),用于特化和扩展一元和二元函数对象。函数适配器分为如下两类:
1)绑定器(binder):它通过将一个操作数绑定到给定值而将二元函数对象转换为一元函数对象。
2)求反器(negator):它将谓词函数对象的真值求反。
1)bind
bind1st //通过绑定第一个参数,使二元的函数对象转化为一元的函数对象
bind2nd //通过绑定第二个参数,使二元的函数对象转化为一元的函数对象
not1 //对一元的函数对象取反
not2 //对二元的函数对象取反
使用的方式:
bind1st( less<int>(), 10)(20);
not2( less<int() )(10,20);
这些Functor看起来好像好像用处不大,但是在和STL中的容器和算法结合在一起使用的时候,就会使得程序显得很简洁.
int i;
vector<int> lv;
for(i = 0; i < 100; i++)
{
lv.push_back(i);
}
//对vector中小于20的数进行记数
cout << count_if(lv.begin(), lv.end(), bind2nd(less<int>(), 20)) << endl;
//由大到小排序
sort(lv.begin(), lv.end(), not2(less<int>()) ) ;
for (i = 0; i < 100; i++)
{
cout << lv.at(i) << endl;
}
函数适配器示例:
/*
* 03.cpp
*
* Created on: Jun 30, 2014
* Author: zfs
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
bool is_odd(int number)
{
return number%2==1;
}
int main()
{
int a[]={1,2,3,4,5};
vector<int> v(a,a+5);
//计算奇数元素的个数
//第一种方法
cout << count_if(v.begin(), v.end(),is_odd) << endl;
//第二种方法
// 这里的bind2nd将二元函数对象modulus转换为一元函数对象。
//bind2nd(op, value) (param)相当于op(param, value)
cout << count_if(v.begin(), v.end(),bind2nd(modulus<int>(),2)) << endl;
//计算大于2的个数
//bind1st(op, value)(param)相当于op(value, param);
cout << count_if(v.begin(), v.end(),
bind1st(less<int>(), 2)) << endl;
return 0;
}
针对成员函数的函数适配器:
1、ptr_fun是指将现有的函数转换为Functor的功能.在STL中提供了这个功能的Functor,就是pointer_to_unary_function和pointer_to_binary_function这两个类,这两个类对应一元和二元两种函数,也就是说,对于调用参数为3个或者多于3个的函数,STL提供的Functor类,无法配接.
2、mem_fun是将某个类中的成员函数转变为Functor的功能.
<pre name="code" class="cpp">/*
* 04.cpp
*
* Created on: Jun 30, 2014
* Author: zfs
*/
#include <iostream>
#include<vector>
#include<functional>
#include<algorithm>
#include<string>
using namespace std;
class Person {
public:
Person(const string& name) :
name_(name) {
}
void Print() const {
cout << name_ << endl;
}
void PrintWithPrefix(string prefix) const {
cout << prefix << name_ << endl;
}
;
protected:
private:
string name_;
};
//成员函数的函数适配器//
void foo(const vector<Person>& v) {
for_each(v.begin(), v.end(), mem_fun_ref(&Person::Print));
for_each(v.begin(), v.end(),
bind2nd(mem_fun_ref(&Person::PrintWithPrefix), "person:"));
}
//成员函数的函数适配器//
void foo2(const vector<Person*>& v) {
for_each(v.begin(), v.end(), mem_fun(&Person::Print));
for_each(v.begin(), v.end(),
bind2nd(mem_fun(&Person::PrintWithPrefix), "person:"));
}
bool check(int elem) {
return elem < 3;
}
int main() {
//
vector<Person> v;
v.push_back(Person("tom"));
v.push_back(Person("jerry"));
foo(v);
vector<Person*> v1;
v1.push_back(new Person("tom1"));
v1.push_back(new Person("jerry1"));
foo2(v1);
/对于一般函数的函数适配器
char* a[] = { "", "BBB", "CCC" };
vector<char*> v3(a, a + 2);
vector<char*>::iterator it1;
it1 = find_if(v3.begin(), v3.end(), bind2nd(ptr_fun(strcmp), ""));
//查找第一个不是空串的字符串
//把一个普通函数转换成二元函数对象
if (it1 != v3.end())
cout << *it1 << endl;
///对于一般函数的函数适配器//
int b[] = { 1, 2, 3, 4, 5 };
vector<int> v4(b, b + 5);
vector<int>::iterator it2;
//it2=find_if(v4.begin(),v4.end(),not1(ptr_fun(check)));
it2 = find_if(v4.begin(), v4.end(), not1(check));
//把函数check转换成一元的函数对象
//查找不小于3的第一个元素
if (it2 != v4.end()) {
cout << *it2 << endl;
}
return 0;
}