什么是仿函数?
我的理解是:仿函数是类里面对()符号的重载。
为什么要使用仿函数?
举个例子:
对于学生结构体的排序问题,可能会有:先按成绩大小排序,若成绩相等就按照学号的先后顺序排序的排序规则。当然我们完全可以不用仿函数,纯手打一个简单的冒泡排序,给它加上一些交换相邻元素的判断条件就可以达到题目的要求,但这样太繁琐了,不如说,如果我都用了algorithm库里面的sort(),那为什么不把sort()的谓语写一下呢?而且sort()方法的时间复杂度还比手打的冒泡排序要小,代码也不容易出错。
还记得用C打了两年半的二分查找,别人C++一句upper_bound()就解决了,最重要的是我还没打对。
综上,仿函数的存在无疑是让代码更加地简洁,可以让写代码的速度变快,写代码的容错率也会变高。
怎么使用仿函数?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class ps
{
public:
ps(){}
//ps空的初始化是保证临时对象的存在
//也就是保证仿函数的实现
ps(int age,int score):age(age),score(score){}
//ps的列表式初始化
bool operator()(const ps& a,const ps& b)
{
count++;
return a.score==b.score?a.age<b.age:a.score>b.score;
//如果a和b的成绩不一样,那么成绩高的在前面
//如果a和b的成绩一样就按照年龄排序,年龄越小越在前面
//count 用来记录排序规则仿函数的调用次数
}
//为sort写的排序规则仿函数
void operator()(const ps& a)
{
cout<<"年龄:"<<a.age<<" 成绩:"<<a.score<<endl;
}
//为for_each写的输出仿函数
int age;
int score;
static int count;
//类中的静态变量可以用来记录函数的调用次数
};
int ps::count = 0;
int main()
{
vector<ps> a;
a.push_back(ps(18,100));
a.push_back(ps(22,100));
a.push_back(ps(12,90));
a.push_back(ps(20,110));
cout<<"排序前:"<<endl;
for_each(a.begin(),a.end(),ps());
sort(a.begin(),a.end(),ps());
cout<<"排序后:"<<endl;
for_each(a.begin(),a.end(),ps());
cout<<"记录:"<<ps::count<<endl;
return 0;
}
构建仿函数前需要了解原函数的底层实现。比如for_each的底层实现就是一个for循环然后把每个元素代入仿函数执行,所以构建for_each的仿函数就只需要一个参数。所以了解algorithm库里面的实用算法的底层是有必要的!
但我们也可以用一般的类外函数实现仿函数的效果
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class ps
{
public:
ps(int age,int score):age(age),score(score){}
//ps的列表式初始化
int age;
int score;
};
void look(const ps& a)
{
cout<<"年龄:"<<a.age<<" 成绩:"<<a.score<<endl;
}
bool cmp(const ps& a,const ps& b)
{
return a.score==b.score?a.age<b.age:a.score>b.score;
//如果a和b的成绩不一样,那么成绩高的在前面
//如果a和b的成绩一样就按照年龄排序,年龄越小越在前面
}
int main()
{
vector<ps> a;
a.push_back(ps(18,100));
a.push_back(ps(22,100));
a.push_back(ps(12,90));
a.push_back(ps(20,110));
cout<<"排序前:"<<endl;
for_each(a.begin(),a.end(),look);
sort(a.begin(),a.end(),cmp);
cout<<"排序后:"<<endl;
for_each(a.begin(),a.end(),look);
return 0;
}
如何把函数作为另外一个函数的参数?
函数指针的定义方法:
指向的函数的返回值类型 (*指针名字)(指向的函数的参数类型列表)
#include <iostream>
#include <algorithm>
using namespace std;
//void (*pf)(pf参数类型列表)
//是指向返回值为void的pf函数
void my_function(int* start,int* end, void (*pf)(int))
{
for(int *i=start;i!=end+1;i++)
pf(*i);
}
void look(int val)
{
cout<<val<<" "<<endl;
}
int main()
{
int a[5]={1,3,2,4,5};
my_function(a,a+4,look);
// 可以达到仿函数的效果
// 也是更为灵活!
return 0;
}
最后总结一下,就拿上面的代码来说,仿函数就相当于是在给algorithm的my_function写look函数,所以这也是为什么了解algorithm的底层实现是那么重要了,当然我们也可以自己写自己的my_function和look,更加灵活但是也更加累,为什么不用现成的呢?(狗头保命)