重載 operator() 的結構體或類別,可像函數一樣被呼叫。STL 演算法(如 for_each)與關聯容器(map, set)大量使用仿函數。
struct print_obj {
void operator()(int a) const { cout << a << endl; }
};
vector<int> v = {1,2,3};
for_each(v.begin(), v.end(), print_obj());
若類別 D 有 void print(),欲對 vector<D*> 每個元素呼叫:
struct D { int num; D(int i=0):num(i) {} void print() { cout << "num=" << num << endl; } };
vector<D*> V;
V.push_back(new D(1));
V.push_back(new D(2));
for_each(V.begin(), V.end(), mem_fun(&D::print));
mem_fun 回傳 mem_fun_t 仿函數物件,內部儲存成員函數指標,operator() 執行 (p->*func)()。
若容器為 vector<D>,改用 mem_fun_ref(&D::print)。
struct B { virtual void print() = 0; };
struct D1 : B { void print() { cout << "D1" << endl; } };
struct D2 : B { void print() { cout << "D2" << endl; } };
vector<B*> V;
V.push_back(new D1); V.push_back(new D2);
for_each(V.begin(), V.end(), mem_fun(&B::print));
透過基類指標呼叫虛擬函數,自動分派到衍生類別實作。
若成員函數有一參數,可用 mem_fun1 綁定,用法類似。
SGI STL stl_function.h 中:
template <class Ret, class Tp>
inline mem_fun_t<Ret,Tp> mem_fun(Ret (Tp::*f)()) {
return mem_fun_t<Ret,Tp>(f);
}
template <class Ret, class Tp>
struct mem_fun_t : public unary_function<Tp*, Ret> {
explicit mem_fun_t(Ret (Tp::*pf)()) : _M_f(pf) {}
Ret operator()(Tp* p) const { return (p->*_M_f)(); }
Ret (Tp::*_M_f)();
};
理解原理後,靈活運用 mem_fun/mem_fun_ref/mem_fun1 可大幅簡化 STL 程式碼,符合物件導向設計。