仿函數就是函數對象,只不過仿函數是老的叫法。仿函數和函數指針都可以作為參數傳入函數,但仿函數的優勢在于,它對類型抽象度高,并且能夠和函數適配器進行匹配,但函數指針卻不行。
類似于迭代器需要包含五種相應類型,為了滿足可配接能力,仿函數需要定義一些類型,這在分析適配器代碼的時候會看到。這個任務交給了一個基類來完成,它的內部定義了這些類型,其它的仿函數只需要繼承這些基類即可。基類定義如下:
~~~
template <class Arg, class Result>
struct unary_function { // 一元仿函數
typedef Arg argument_type; // 函數/仿函數唯一參數類型
typedef Result result_type; // 函數/仿函數返回值
};
template <class Arg1, class Arg2, class Result>
struct binary_function { // 二元仿函數
typedef Arg1 first_argument_type; // 仿函數參數1
typedef Arg2 second_argument_type; // 仿函數函數2
typedef Result result_type; // 仿函數返回類型
};
~~~
用戶自定義的仿函數,只要繼承了相應的基類,就具有了可配接能力。以下是測試代碼:
~~~
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <class T>
class les: public binary_function<T, T, T> {
public:
bool operator() (const T &lhs, const T &rhs) const
{ return lhs < rhs; }
};
int main()
{
int array[] = {3,4,1,7,5,9,5};
vector<int> vec(array, array+7);
// 找出容器內小于10的元素個數
cout << count_if(vec.begin(), vec.end(), bind2nd(les<int>(), 7));
return 0;
}
~~~
運行結果:

注意上面的les仿函數繼承自二元仿函數binary_function,這樣它就能與適配器bind2nd正常配接,否則會在運行期發生錯誤。
按操作數個數劃分,可分為:
- 一元仿函數
- 二元仿函數
按功能劃分,可分為:
- 算術運算
- 關系運算
- 邏輯運算
以plus仿函數為例:
~~~
template <class T>
struct plus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x + y; }
};
~~~
其它的仿函數幾乎都是這個模樣,有些細節上略有不同,這是根據操作符本身的性質決定的。
參考:
《STL源碼剖析》 第七章。
- 前言
- 順序容器 — heap
- 關聯容器 — 紅黑樹
- 關聯容器 — set
- 關聯容器 — map
- 關聯容器 — hashtable
- 關聯容器 — hash_set
- 關聯容器 — hash_map
- 算法 — copy
- 順序容器 — stack
- 順序容器 — queue
- 順序容器 — priority_queue
- 順序容器 — slist
- construct()和destroy()
- 空間配置器
- 函數適配器
- 迭代器以及“特性萃取機”iterator_traits
- 算法 — partial_sort
- 算法 — sort
- 仿函數
- 適配器(adapters)
- C++簡易vector
- C++簡易list
- STL算法實現
- C++模板Queue