C++ STL 基础及应用(7) 函数对象(仿函数)
STL,C++,函数对象,仿函数,functional2016-06-08
把函数作为对象是程序设计的新思维。STL 通过重载类中的 operator() 函数实现函数对象功能,不但可以对容器中的数据进行各种各样的操作,而且能够维护自己的状态。因此,与标准 C 库函数相比,函数对象更为通用。
#include <iostream>
using namespace std;
int Add(int x,int y)
{
return x+y;
}
int main()
{
int (*f)(int x,int y); //声明一个函数指针
f=Add; //函数指针赋值
//也可以写成: f=&Add;
cout<<f(1,2); //像普通函数一样调用
return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int sum=0;
void f(int x)
{
sum+=x;
}
int main()
{
vector<int> v;
for(int i=0;i<100;i++)
{
v.push_back(i);
}
for_each(v.begin(),v.end(),f);
cout<<sum;
return 0;
}for_each()函数定义于 <algorithm> 中,前两个参数为限定范围的迭代器,最后一个参数为一个函数指针,for_each()根据迭代器限定范围每次取出一个值作为参数执行第三个参数指向的函数。在本例中,即从 v.begin() 开始依次取出值 x,执行 f(x);直到 v.end() 为止。注意到,为了实现这个求和功能,使用了一个
sum 全局变量,并且 f(int) 是一个全局函数。随着 C++ 面向对象的思想的普及和发展,绝大多数的功能都封装在了类中,实现模块化编程。那么上述函数将被封装成如下形式:class Sum
{
private:
int sum;
public:
Sum(){sum=0;}
void f(int x)
{
sum+=x;
}
int GetSum(){return sum;}
};封装性有了,那么该如何方便地调用 Sum::f() 方法呢? 推而广之,如何调用所需类中的所需函数呢?这是一个十分关键的问题。函数对象的使用能够简介快速地使用所需类中对象的函数。class Sum
{
private:
int sum;
public:
Sum(){sum=0;}
void operator()(int x)
{
sum+=x;
}
int GetSum(){return sum;}
};注意!与之前的区别在于重载了 operator() 而不是 f() 函数。#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Sum
{
private:
int sum;
public:
Sum(){sum=0;}
void operator()(int x)
{
sum+=x;
}
int GetSum(){return sum;}
};
int main()
{
vector<int> v;
for(int i=0;i<100;i++)
{
v.push_back(i);
}
Sum s=for_each(v.begin(),v.end(),Sum());
cout<<s.GetSum();
return 0;
}此时用 Sum s 来接收 for_each() 返回的最终结果。STL 中定义了很多函数对象供编程者使用,包括大量算法,在本文后面会详细介绍。template<class _Arg,class _Result>
struct unary_function
{
typedef _Result result_type;
};两个模板参数,_Arg 为输入参数类型,_Result 为返回类型。template<class _Arg1,class _Arg2,class _Result>
struct binary_function
{
typedef _Arg1 first_argument_type;
typedef _Arg2 second_argument_type;
typedef _Result result_type;
};用户虽然自定义的函数对象也能正确编译并使用,但是最好继承上述两者之一,因为对于继承者,STL 能对其进行二次扩展,比如可以使用函数适配器对其进行再次封装,而自己定义的函数对象则缺乏扩展性。#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
class student
{
private:
string name;
int grade;
public:
student(string name,int grade)
{
this->name=name;
this->grade=grade;
}
friend ostream& operator << (ostream& o,const student& s)
{
cout<<s.name<<"\t"<<s.grade<<endl;
return o;
}
bool operator < (const student& s) const
{
return this->grade < s.grade;
}
};
template <class _Arg1,class _Arg2>
class binary_sort : public binary_function<_Arg1,_Arg2,bool>
{
public:
bool operator()(_Arg1 a1,_Arg2 a2)
{
return a1 < a2;
}
};
int main()
{
vector<student> v;
v.push_back(student("秦始皇",80));
v.push_back(student("康熙",60));
v.push_back(student("李世民",90));
sort(v.begin(),v.end(),binary_sort<const student&,const student&>()); //利用二元函数排序
copy(v.begin(),v.end(),ostream_iterator<student>(cout)); //输出
return 0;
}输出:#include <functional>
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
class Complex
{
private:
float r; //实数部分
float v; //虚数部分
public:
Complex()
{
this->r=0.0f;
this->v=0.0f;
}
Complex(float r,float v)
{
this->r=r;
this->v=v;
}
friend ostream& operator << (ostream& o,const Complex& c)
{
cout<<c.r<<"+"<<c.v<<"i"<<endl;
return o;
}
Complex operator + (const Complex& c) const
{
Complex temp(this->r+c.r,this->v+c.v);
return temp;
}
};
int main()
{
//两个复数相加
Complex c1(1,1);
Complex c2(2,2);
Complex rusult1=plus<Complex>()(c1,c2);
cout<<rusult1;
//好几个复数累加
Complex c3(3,3);
Complex c4(4,4);
Complex c5(5,5);
vector <Complex> v;
v.push_back(c1);
v.push_back(c2);
v.push_back(c3);
v.push_back(c4);
v.push_back(c5);
Complex c;
Complex result2=accumulate(v.begin(),v.end(),c,plus<Complex>());
cout<<result2;
return 0;
}输出:#include <functional>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
class student
{
private:
string name;
int number;
public:
student(string name,int number)
{
this->name=name;
this->number=number;
}
bool show()
{
cout<<endl<<"name:"<<name<<"\tnumber:"<<number;
return true;
}
};
bool f(int a)
{
return a>7;
}
bool g(int a,int b)
{
return a>b;
}
int main()
{
int a[]={10,9,8,7,6,5,4,3,2,1};
int n1=count_if(a,a+sizeof(a)/sizeof(int),bind1st(less<int>(),4));
int n2=count_if(a,a+sizeof(a)/sizeof(int),bind2nd(less<int>(),4));
int n3=count_if(a,a+sizeof(a)/sizeof(int),not1(bind2nd(less<int>(),4)));
sort(a,a+sizeof(a)/sizeof(int),not2(less<int>()));
copy(a,a+sizeof(a)/sizeof(int),ostream_iterator<int>(cout," "));
int n4=count_if(a,a+sizeof(a)/sizeof(int),ptr_fun(f));
int n5=count_if(a,a+sizeof(a)/sizeof(int),bind2nd(ptr_fun(g),8));
student s1("秦始皇",1001);
student s2("乾隆",1002);
vector<student> v1;
v1.push_back(s1);
v1.push_back(s2);
vector<student *> v2;
v2.push_back(&s1);
v2.push_back(&s2);
for_each(v1.begin(),v1.end(),mem_fun_ref(&student::show));
for_each(v2.begin(),v2.end(),mem_fun(&student::show));
cout<<endl<<"n1="<<n1<<" n2="<<n2<<" n3="<<n3<<" n4="<<n4<<" n5="<<n5<<endl;
return 0;
}输出:#include <iostream>
#include <functional>
using namespace std;
int Myminus(int x,int y)
{
return x-y;
}
class MyNum
{
private:
int a,b;
public:
MyNum(){a=4;b=5;}
MyNum(int a,int b)
{
this->a=a;
this->b=b;
}
int Add(){return a+b;}
int Cal(int c,int d){return a+b+c+d;}
};
int main()
{
function<int(int,int)> f1=bind(Myminus,placeholders::_1,placeholders::_2);
int r1=f1(3,2);
cout<<r1<<endl;
function<int(int)> f2=bind(Myminus,placeholders::_1,4);
int r2=f2(7);
cout<<r2<<endl;
function<int()> f3=bind(Myminus,7,5);
int r3=f3();
cout<<r3<<endl;
function<int(int,int)> f4=bind(Myminus,placeholders::_2,placeholders::_1);
int r4=f4(7,4);
cout<<r4<<endl;
MyNum num5;
function<int()> f5=bind(&MyNum::Add,num5);
int r5=f5();
cout<<r5<<endl;
MyNum num6(3,4);
function<int(MyNum&)> f6=bind(&MyNum::Add,placeholders::_1);
int r6=f6(num6);
cout<<r6<<endl;
MyNum num7(1,2);
function<int(MyNum&,int,int)> f7=bind(&MyNum::Cal,placeholders::_1,placeholders::_2,placeholders::_3);
int r7=f7(num7,3,4);
cout<<r7<<endl;
return 0;
}输出:#include <iostream>
#include <functional>
using namespace std;
void f(int &a,int &b,const int &c)
{
cout<<"运行函数中: "<<a<<"\t"<<b<<"\t"<<c<<endl;
++a;
++b;
//++c;
}
int main ()
{
int a=1,b=2,c=3;
auto fun = bind(f,a,ref(b),cref(c));
a=6;
b=7;
c=8;
cout<<"运行函数前: "<<a<<"\t"<<b<<"\t"<<c<<endl;
fun();
cout<<"运行函数后: "<<a<<"\t"<<b<<"\t"<<c<<endl;
return 0;
}输出: