仿函数是行为类似函数的对象,所谓函数行为,是指可以“使用小括号传递参数,藉以调用某个东西”。
下面是仿函数定义的一般形式:
class X
{
public:
return type operator()(参数) const
{
}
};
下面是一个使用仿函数的简单实例:
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
template<class T>
class Print
{
public:
void operator()(T & elem)const
{
cout << elem << " ";
}
};
void main()
{
list<int> mylist;
for (int i = 1; i <= 10; i++)
{
mylist.push_back(i);
}
for_each(mylist.begin(), mylist.end(), Print<int>());
cin.get();
}
这里Print<int>()创建一个此类别的临时对象,当作for_each的一个参数。
另外一个使用仿函数的例子:
#include<iostream>
#include<list>
#include<algorithm>
#include<iterator>
using namespace std;
template<class T>
class IntSequence
{
public:
IntSequence(int initVal) :value(initVal)
{
}
int operator()()
{
return value++;
}
private:
T value;
};
void main()
{
list<int> mylist;
generate_n(back_inserter(mylist), 5, IntSequence<int>(1));
for (auto i : mylist)
{
cout << i << " ";
}
cout << "\n";
generate_n(front_inserter(mylist), 5, IntSequence<int>(10));
for (auto i : mylist)
{
cout << i << " ";
}
cin.get();
}
C++提供了许多预定义的仿函数,具体如下表:
仿函数 | 效果 |
---|---|
negate<type>() | -param |
plus<type>() | param1+param2 |
minus<type>() | param1-param2 |
multiplies<type>() | param1*param2 |
divides<type>() | param1/param2 |
modulus<type>() | param1%param2 |
equal_to<type>() | param1==param2 |
not_equal_to<type>() | param1!=param2 |
less<type>() | param1<param2 |
greater<type>() | param1>param2 |
less_equal<type>() | param1<=param2 |
greater_equal<type>() | param1>=param2 |
logical_not<type>() | !param |
logical_and<type>() | param1&¶m2 |
logical_or<type>() | param1||param2 |
要使用这些仿函数,必须包含头文件<functional>
默认情况,set容器是以less<>为预设准则,按从小到大排序
下面使用仿函数greater<int>对容器进行从大到小的初始化
#include<iostream>
#include<set>
#include<functional>
using namespace std;
using std::function;
void main()
{
set<int,greater<int> > myset;
for (int i = 1; i <= 10; i++)
{
myset.insert(i);
}
for (auto i : myset)
{
cout << i << " ";
}
cout << endl;
cin.get();
}
下面例子使用仿函数multiplies<type>()对容器中每个元素乘2:
#include<iostream>
#include<list>
#include<functional>
#include<algorithm>
#include<iterator>
using namespace std;
using std::function;
void main()
{
list<int> mylist;
for (int i = 1; i <= 5; i++)
{
mylist.push_back(i);
}
for (auto i : mylist)
{
cout << i << " ";
}
cout << endl;
transform(mylist.begin(), mylist.end(), ostream_iterator<int>(cout, " "), bind2nd(multiplies<int>(), 2));
cin.get();
}
这里的bind2nd是一个函数配接器,实际上bind2nd是将一个二元仿函数(multiplies<>)转换为一元仿函数。它通常将第二参数传给“由第一参数
指出”的二元仿函数。函数配接器本身也是一个仿函数。
所谓“函数配接器”是指能够将仿函数和另一个仿函数(或某一个值,或某个一般函数)结合起来的仿函数。函数配接器也声明于<functional>.
表达式 | 效果 |
---|---|
bind1st(op,value) | op(value,param) |
bind2nd(op,value) | op(value,param) |
not1(op) | !op(param) |
not2(op) | !op(param1,param2) |
下面的例子使用not1()和bind2nd()删除容器中的所有偶数:
#include<iostream>
#include<list>
#include<algorithm>
#include<functional>
#include<iterator>
using namespace std;
using std::function;
void main()
{
list<int> mylist;
for (int i = 1; i <= 10; i++)
{
mylist.push_back(i);
}
for (auto i : mylist)
{
cout << i << " ";
}
cout << endl;
list<int>::iterator pos;
pos = remove_if(mylist.begin(), mylist.end(), not1(bind2nd(modulus<int>(), 2)));
mylist.erase(pos, mylist.end());
for (auto i : mylist)
{
cout << i << " ";
}
cin.get();
}