把函数作为对象是程序设计的新思维。STL 通过重载类中的 operator() 函数实现函数对象功能,不但可以对容器中的数据进行各种各样的操作,而且能够维护自己的状态。因此,与标准 C 库函数相比,函数对象更为通用。
C++98 标准和C++11标准下 STL 内置函数对象的详细介绍、适配器类的使用。包括 bind1st bind2nd not1 not2 mem_fun mem_fun_ref ptr_fun bind ref cref 的使用。
#include
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<
#include
#include
#include
using namespace std;
int sum=0;
void f(int x)
{
sum+=x;
}
int main()
{
vector v;
for(int i=0;i<100;i++)
{
v.push_back(i);
}
for_each(v.begin(),v.end(),f);
cout<
for_each()函数定义于 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
#include
#include
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 v;
for(int i=0;i<100;i++)
{
v.push_back(i);
}
Sum s=for_each(v.begin(),v.end(),Sum());
cout<
此时用 Sum s 来接收 for_each() 返回的最终结果。STL 中定义了很多函数对象供编程者使用,包括大量算法,在本文后面会详细介绍。template
struct unary_function
{
typedef _Result result_type;
};
两个模板参数,_Arg 为输入参数类型,_Result 为返回类型。template
struct binary_function
{
typedef _Arg1 first_argument_type;
typedef _Arg2 second_argument_type;
typedef _Result result_type;
};
用户虽然自定义的函数对象也能正确编译并使用,但是最好继承上述两者之一,因为对于继承者,STL 能对其进行二次扩展,比如可以使用函数适配器对其进行再次封装,而自己定义的函数对象则缺乏扩展性。#include
#include
#include
#include
#include
#include
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<grade < s.grade;
}
};
template
class binary_sort : public binary_function<_Arg1,_Arg2,bool>
{
public:
bool operator()(_Arg1 a1,_Arg2 a2)
{
return a1 < a2;
}
};
int main()
{
vector v;
v.push_back(student("秦始皇",80));
v.push_back(student("康熙",60));
v.push_back(student("李世民",90));
sort(v.begin(),v.end(),binary_sort()); //利用二元函数排序
copy(v.begin(),v.end(),ostream_iterator(cout)); //输出
return 0;
}
输出:#include
#include
#include
#include
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<r+c.r,this->v+c.v);
return temp;
}
};
int main()
{
//两个复数相加
Complex c1(1,1);
Complex c2(2,2);
Complex rusult1=plus()(c1,c2);
cout< 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());
cout<
输出:#include
#include
#include
#include
#include
#include
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<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(),4));
int n2=count_if(a,a+sizeof(a)/sizeof(int),bind2nd(less(),4));
int n3=count_if(a,a+sizeof(a)/sizeof(int),not1(bind2nd(less(),4)));
sort(a,a+sizeof(a)/sizeof(int),not2(less()));
copy(a,a+sizeof(a)/sizeof(int),ostream_iterator(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 v1;
v1.push_back(s1);
v1.push_back(s2);
vector 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<输出:
10 9 8 7 6 5 4 3 2 1
name:秦始皇 number:1001
name:乾隆 number:1002
n1=6 n2=3 n3=7 n4=3 n5=2
程序解释如下:
(1)less() 原型为:
template
struct less : public binary_function<_Ty, _Ty, bool>
{
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{
return (_Left < _Right);
}
};
即该函数比较两个参数,若第一个参数小于第二个参数则返回 true。bind1st(less(),4))将 less() 函数的第一个参数绑定为 4,将其适配成为一个新的函数,count_if()函数将迭代器范围内的元素传入该新的函数并且计数返回几个 true,因此该行语句的意义即为计数数组中比 4 的元素个数,5~10一共6个数,所以 n1=6。
(2)bind2nd(less(),4)) 即是将 less() 的第二个参数绑定为4,那么该行语句实际计数的是小于 4 的数,因此 n2=3。
(3)not1() 对一元函数结果取反(返回 true 时改为 false,反之则反),因此 n3 即为大于等于 4 的元素个数,n3=7。
(4)not2() 对二元函数结果取反,因此 sort(a,a+sizeof(a)/sizeof(int),not2(less())) 即为按从大到小排序。
(5)ptr_fun() 为普通函适配器,使一个普通函数能够被 STL 中的函数、算法调用。如代码中的 bind2nd(ptr_fun(g),8)) 若写成 bind2nd(g,8)) 则为错误,因为 STL 不接受未经 ptr_fun() 转换的函数。
(6)mem_fun_ref、mem_fun 是类的成员函数适配器,两者的区别在于:若集合是基于对象的,形如 vector,则用 mem_fun_ref;若集合是基于对象指针的,形如 vector,则用 men_fun。
注意!取成员函数地址时需要加上 "&" 符号不能省略,代码接近最后两行 for_each() 里面 (&student::show) 写成 (student::show) 则编译器会报错。
C++11标准下函数对象使用详解
C++11 函数适配器表:
系统函数对象、mem_fn() 与 mem_fun() 使用类似,not1()/not2() 与C++98标准里的 not1()/not2() 使用类似,就都不再赘述了。
function
我们知道,在C++中,可调用实体主要包括函数,函数指针,函数引用,可以隐式转换为函数指定的对象,或者实现了opetator()的对象(即函数对象)。C++11中,新增加了一个std::function对象,std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。
bind()
C++98中,有两个函数 bind1st() 和 bind2nd(),它们分别可以用来绑定函数对象的第一个和第二个参数,它们都是只可以绑定一个参数。各种限制,使得 bind1st() 和 bind2nd() 的可用性大大降低。C++11中,提供了std::bind(),它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定,这个 bind() 才是真正意义上的绑定,有了它,bind1st() 和 bind2nd() 就没啥用武之地了,因此在 C++11 中不推荐使用 bind1st() 和 bind2nd() 了。
function/bind()使用如下:
#include
#include
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 f1=bind(Myminus,placeholders::_1,placeholders::_2);
int r1=f1(3,2);
cout< f2=bind(Myminus,placeholders::_1,4);
int r2=f2(7);
cout< f3=bind(Myminus,7,5);
int r3=f3();
cout< f4=bind(Myminus,placeholders::_2,placeholders::_1);
int r4=f4(7,4);
cout< f5=bind(&MyNum::Add,num5);
int r5=f5();
cout< f6=bind(&MyNum::Add,placeholders::_1);
int r6=f6(num6);
cout< f7=bind(&MyNum::Cal,placeholders::_1,placeholders::_2,placeholders::_3);
int r7=f7(num7,3,4);
cout<
输出:#include
#include
using namespace std;
void f(int &a,int &b,const int &c)
{
cout<<"运行函数中: "<
输出: