一 仿函數functor
1. 概述
仿函數(functors)是早期的命名,C++標準規格定案後採用的新名稱是函數對象(function objects)(也就是一種具有函數特質的對象)。
仿函數的作用:在C++的STL提供的各種算法,例如sort()。往往有兩個版本,其中一個是最長用的某種運算的版本(operator<);第二個版本則表現出最泛化的演算流程,允許用戶“以template參數來指定所需要採取的策略”。
仿函數產生的原因:由於函數指針畢竟不能滿足STL對抽象對象的需求,也不能滿足軟件積木的需求——函數指針無法和STL其它組件(如配接器adapter)搭配使用,產生更靈活的變化。
template<class T>
class comp:public binary_function<T, T, bool>
{
public:
bool operator()(T in1, T in2) const
{
return (in1>in2);
}
};
int a[] = {0, 1, 2, 3, 4, 5, 6,99, 8, 9};
std::vector<int> v(a, a+10);
comp<int> comp_object;
vector<int>::iterator pos;
pos = find_if(v.begin(), v.end(),bind2nd(comp<int>(), 10));//使用仿函數實現
cout <<comp_object(6, 3) << endl; //使用對象調用
cout << comp<int>()(1, 2) << endl; //使用仿函數實現
cout <<" the num in v > 10 is " << *pos << endl;
class my_count1
{
public:
T threshold;
my_count1(T a)
{
threshold = a;
}
bool operator()(T num)
{
return (num < threshold);
}
};
int main(){
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> v_a(a, a+10);
cout << "count: " << std::count_if(v_a.begin(), v_a.end(), my_count1<int>(11)); //bind1st
return 0;
}
二 函數適配器:
適配器:相當於提供了一個接口,使得某些不適用於特定對象的方法可以被該對象所用,本質上,適配器是使一事物的行爲類似於另一事物的行爲的一種機制。
函數適配器共有如下3種:
1. 綁定器,有兩個: std::for_each(iterator, iterator, func); 當需要傳入兩個參數給for_each() 時, 需用bind2nd,或bind1st bind1st (函數對象,指定值); (過時) 將指定值綁定到函數對象的第1個參數上。 bind2nd (函數對象,指定值); (過時) 將指定值綁定到函數對象的第2個參數上。 bind (函數對象,指定值… C++11) 綁定的參數的個數不受限制;對於不事先綁定的參數,需要傳std::placeholders進去,從 _1 開始,依次遞增(佔位符) 2. 否定器,也有兩個: ——not1() //用於逆轉一元斷言 ——not2() //用於逆轉二元斷言 3. 成員函數適配器,也是兩個: ——mem_fun() //容器參數爲類指針 ——mem_fun_ref() //容器參數爲類對象 綁定的參數的個數不受限制;對於不事先綁定的參數,需要傳std::placeholders進去,從_1開始,依次遞增 4. 函數指針適配器 ptf_fun 將函數指針轉換爲函數對象 |
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class Print_int
{
public:
void operator()(int &a) const
{
cout << a << endl;
}
};
class Person
{
public:
Person(string newname, int newage):name(newname), age(newage){}
void showPerson()const
{
cout << "member function: "<< "name " << name << " age " << age << endl;
}
string name;
int age;
};
void print_Person(Person &p)
{
cout << "name: " << p.name <<endl;
}
void PrintFunc(Person p, int val){
cout << "ptr_fun() + bind2nd: "<< "p.name " << p.name << " val " << val << endl;
}
class PrintClass: public binary_function< Person, int, void>
{
public:
void operator()( Person &p, int val)const
{
cout<< "fun adaptor + bind2nd: " << "p.name " << p.name << " val " << val << endl;
}
};
void mystack(){
vector<int> v(10,2);
vector<Person> vv;
vv.reserve(5);
Person p0("elsa",20);
Person p1("elsa1",21);
Person p2("elsa2",22);
vv.push_back(p0);
vv.push_back(p1);
vv.push_back(p2);
cout << "vv.capacity: " << vv.capacity() << " vv.size: " << vv.size() <<endl;
for_each(v.begin(), v.end(), [](int &a){ cout << "lameda: " << a << endl; }); //lameda c++11
for_each(vv.begin(), vv.end(),print_Person); //function pointer
for_each(v.begin(), v.end(),Print_int()); //functor
for_each(vv.begin(), vv.end(),mem_fun_ref(&Person::showPerson)); //member function adaptor
// 用於傳兩個參數,bind2nd()第二個參數爲 另一參數
// 用於傳兩個參數,bind1st()第一個參數爲 另一參數
for_each(vv.begin(), vv.end(),bind2nd(PrintClass(), 50)); //fun adaptor + bind2nd
for_each(vv.begin(), vv.end(),bind2nd(ptr_fun(PrintFunc), 50)); //ptr_fun adaptor
}
int main(){
mystack();
return 0;
}
plus: 1. for_each( iterator, iterator, fun ) , sort(iterator, iterator, fun) 等算法的第三個參數, 若爲函數不需要(), 若爲類則需要().
2. 掌握functor 的用法
3.bind2nd 與bind1st
4. mem_fun / ptr_fun