一. 概念:
函数对象function objects,又名仿函数,是一个定义了operator()操作的对象。
- class FunctionObjectType {
- public:
- void operator() {
- statements
- }
- };
class FunctionObjectType {
public:
void operator() {
statements
}
};
二. 仿函数当做排序准则:
程序员经常需要将某些class object以已序的形式放到容器中,然而有时你无法使用一般的operator<来对这些对象排序,这时可以仿函数。
- #include <iostream>
- #include <string>
- #include <set>
- #include <algorithm>
- using namespace std;
- class Person {
- public:
- string firstname() const;
- string lastname() const;
- ...
- };
- /* 仿函数,按名字排序
- * - operator() returns whether a person is less than another person
- */
- class PersonSortCriterion {
- public:
- bool operator() (const Person& p1, const Person& p2) const {
- /* a person is less than another person
- * - if the last name is less
- * - if the last name is equal and the first name is less
- */
- return p1.lastname()<p2.1astname() ||
- (! (p2.1astname()<p1.lastname()) &&
- p1.firstname()<p2.firstname());
- }
- };
- int main()
- {
- //声名 set ,用这个仿函数
- typedef set<Person,PersonSortCriterion> PersonSet;
- //create such a collection
- PersonSet coll;
- ...
- //do something with the elements
- PersonSet::iterator pos;
- for (pos = coll.begin(); pos != coll.end();++pos) {
- ...
- }
- ...
- }
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
class Person {
public:
string firstname() const;
string lastname() const;
...
};
/* 仿函数,按名字排序
* - operator() returns whether a person is less than another person
*/
class PersonSortCriterion {
public:
bool operator() (const Person& p1, const Person& p2) const {
/* a person is less than another person
* - if the last name is less
* - if the last name is equal and the first name is less
*/
return p1.lastname()<p2.1astname() ||
(! (p2.1astname()<p1.lastname()) &&
p1.firstname()<p2.firstname());
}
};
int main()
{
//声名 set ,用这个仿函数
typedef set<Person,PersonSortCriterion> PersonSet;
//create such a collection
PersonSet coll;
...
//do something with the elements
PersonSet::iterator pos;
for (pos = coll.begin(); pos != coll.end();++pos) {
...
}
...
}
三. 拥有内部状态的仿函数:
- #include <iostream>
- #include <list>
- #include <algorithm>
- #include "print.hpp"
- using namespace std;
- class IntSequence {
- private:
- int value;
- public:
- //constructor
- IntSequence (int initialValue)
- : value(initialValue) {
- }
- //''function call''
- int operator() () {
- return value++;
- }
- };<span><span class="comment"></span></span>
- int main()
- {
- list<int> coll;
- //insert values from 1 to 9
- generate_n (back_inserter(coll), //start
- 9, //number of elements
- IntSequence (1)); //generates values
- PRINT_ELEMENTS(coll); //1 2 3 4 5 6 7 8 9
- //replace second to last element but one with values starting at 42
- generate (++coll.begin(), //start
- --coll.end(), //end
- IntSequence (42)); //generates values
- PRINT_ELEMENTS(coll); //1 42 43 44 45 46 47 48 9
- }
#include <iostream>
#include <list>
#include <algorithm>
#include "print.hpp"
using namespace std;
class IntSequence {
private:
int value;
public:
//constructor
IntSequence (int initialValue)
: value(initialValue) {
}
//''function call''
int operator() () {
return value++;
}
};
int main()
{
list<int> coll;
//insert values from 1 to 9
generate_n (back_inserter(coll), //start
9, //number of elements
IntSequence (1)); //generates values
PRINT_ELEMENTS(coll); //1 2 3 4 5 6 7 8 9
//replace second to last element but one with values starting at 42
generate (++coll.begin(), //start
--coll.end(), //end
IntSequence (42)); //generates values
PRINT_ELEMENTS(coll); //1 42 43 44 45 46 47 48 9
}
注:generate/generate_n 通过一个数值产生器类生成的数值来初始化一个容器, 通过将产生器函数gen返回的值赋给由迭代器指定的[first, last) or [first, first + n)范围内的所有元素, generate和generate_n算法初始化或重新初始化了一个序列。
以引用方式传递仿函数:
- generate_n<back_insert_iterator<list<int> >, int, IntSequence&>
- (back_inserter(coll), //start
- 4, //number of elements
- seq); //generates values
generate_n<back_insert_iterator<list<int> >, int, IntSequence&>
(back_inserter(coll), //start
4, //number of elements
seq); //generates values
调用后,seq的值已经改变,下次再调用会用上次的值。
三. for_each()的返回值
for_each()可以返回其仿函数,这样你可以返回值获取仿函数的状态了。
- MeanValue mv = for_each (coll.begin(), coll.end(), //range
- MeanValue()); //operation
- cout << "mean value: " << mv.value() << endl;
MeanValue mv = for_each (coll.begin(), coll.end(), //range
MeanValue()); //operation
cout << "mean value: " << mv.value() << endl;
四. 预定义的仿函数
#include <functional>
negate<type>() | - param |
plus<type>() | param1 + param2 |
minus<type>() | param 1 - 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 && param2 |
logical_or<type> () | param1 | | param2 |
- typedef set<int, greater<int> > IntSet;
- typedef set<int, less<int> > IntSet;