仿函数
把类对象像函数名一样使用,所认称为仿函数,仿函数本质不是函数而是类对象。
仿函数(functor)就是使一个类,使用看上去像一个函数。实现就是类中实现一个operator(),这个类就有了类似函数的行为,这个类就是一个仿函数类了。
operator( ) 语法格式
class 类名
{
返值类型 operator()(参数类型)
函数体
}
使用仿函数实现求幂运算
代码演示:
#include <iostream>
#include <math.h>
using namespace std;
class Pop
{
public:
double operator()(double x, int y)
{
int resu = 1;
for (int tmp = 0; tmp < y; tmp++)
resu *= x;
return resu;
}
};
int main()
{
int a = 5;
cout << pow(a,2) << endl; //系统提供的函数接口
Pop mypow;
cout << mypow(a, 2) << endl; //仿函数实现
//等价于mypow.operator()(a, 2)
return 0;
}
运行结果:
我们可以到上面生成的类对象以函数的形式使用。这种现象就叫做仿函数。
其本质是实现 ( ) 重载。
std::sort 中回调函数
简单引入vector
#include <iostream>
#include <math.h>
#include <algorithm> //算法
#include <vector> //STL-vector
using namespace std;
int main()
{
int arr[6] = {1,3,5,8,6,4};
vector<int> vi(arr, arr + 6);
/*
* vector 模板
* vector<int> 模板实例化 也就是 类
* vector<int> vi 类生成对象
* vector<int> vi(arr, arr + 6); 类生成对象的入参
*/
vector<int>::iterator itr;
for (itr = vi.begin(); itr != vi.end(); ++itr)//C++98标准打印数组
{
cout << *itr << endl;
}
cout << "=================================="<<endl;
for (auto itr = vi.begin(); itr != vi.end(); ++ itr)//C++11标准打印数组
{
cout << *itr << endl;
}
cout << "==================================" << endl;
for (auto i : vi) //C++11标准打印数组
{
cout << i << endl;
}
return 0;
}
运行结果:
代码演示:
#include <iostream>
#include <math.h>
#include <algorithm> //算法
#include <vector> //STL-vector
using namespace std;
bool myCompare(int a, int b)
{
return a > b;
}
int main()
{
int arr[6] = {1,3,5,8,6,4};
vector<int> vi(arr, arr + 6);
/*
* vector 模板
* vector<int> 模板实例化 也就是 类
* vector<int> vi 类生成对象
* vector<int> vi(arr, arr + 6); 类生成对象的入参
*/
sort(vi.begin(),vi.end(), myCompare); //排序
vector<int>::iterator itr;
for (itr = vi.begin(); itr != vi.end(); ++itr)//C++98标准打印数组
{
cout << *itr << endl;
}
return 0;
}
运行结果为:
我们可以看到实现了排序。
但是C++中这种方法不被看好,因为有更好的方法:
代码演示:
#include <iostream>
#include <math.h>
#include <algorithm> //算法
#include <vector> //模板
using namespace std;
bool myCompare(int a, int b)
{
return a > b;
}
class Compare
{
public:
bool operator()(int a, int b)
{
return a > b;
}
};
int main()
{
int arr[6] = {1,3,5,8,6,4};
vector<int> vi(arr, arr + 6);
/*
* vector 模板
* vector<int> 模板实例化 也就是 类
* vector<int> vi 类生成对象
* vector<int> vi(arr, arr + 6); 类生成对象的入参
*/
Compare c; //生成类对象
sort(vi.begin(),vi.end(), c); //排序
//等价于sort(vi.begin(),vi.end(), c.operator());
vector<int>::iterator itr;
for (itr = vi.begin(); itr != vi.end(); ++itr)//C++98标准打印数组
{
cout << *itr << endl;
}
return 0;
}
运行结果为:
换一种写法,直接传递匿名对象:
代码演示:
#include <iostream>
#include <math.h>
#include <algorithm> //算法
#include <vector> //模板
using namespace std;
bool myCompare(int a, int b)
{
return a > b;
}
class Compare
{
public:
bool operator()(int a, int b)
{
return a > b;
}
};
int main()
{
int arr[6] = {1,3,5,8,6,4};
vector<int> vi(arr, arr + 6);
/*
* vector 模板
* vector<int> 模板实例化 也就是 类
* vector<int> vi 类生成对象
* vector<int> vi(arr, arr + 6); 类生成对象的入参
*/
//sort(vi.begin(),vi.end(), myCompare); //排序 但是C++中这种方法不被看好
//Compare c;
//sort(vi.begin(),vi.end(), c); //排序 (使用对象)
sort(vi.begin(),vi.end(), Compare()); //排序 (回调仿函数实现)使用匿名对象
vector<int>::iterator itr;
for (itr = vi.begin(); itr != vi.end(); ++itr)//C++98标准打印数组
{
cout << *itr << endl;
}
return 0;
}
运行结果为:
functor 的优势
那么上面传递匿名对象有什么优势呢?
functor 的优势在于,是对象形式,可以携带更多的的信息,用于作出判断。
比如,我们可以在对象初始化的时候,传入参数来决定状态,而不用去修改原代码。
调用类对象可以传递参数,可以携带变量。
代码演示:
#include <iostream>
#include <math.h>
#include <algorithm> //算法
#include <vector> //STL-vector
using namespace std;
bool myCompare(int a, int b)
{
return a > b;
}
class Compare
{
public:
Compare(bool b = true)
:flag(b)
{}
bool operator()(int a, int b)
{
if(flag == true)
return a > b; //按照从大到小的顺序排序
else
return a < b; //按照从小到大的顺序排序
}
private:
bool flag;
};
int main()
{
int arr[6] = {1,3,5,8,6,4};
vector<int> vi(arr, arr + 6);
/*
* vector 模板
* vector<int> 模板实例化 也就是 类
* vector<int> vi 类生成对象
* vector<int> vi(arr, arr + 6); 类生成对象的入参
*/
sort(vi.begin(),vi.end(), Compare(true)); //降序排列
vector<int>::iterator itr;
for (itr = vi.begin(); itr != vi.end(); ++itr)//C++98标准打印数组
{
cout << *itr << endl;
}
sort(vi.begin(), vi.end(), Compare(false)); //升序排列
cout << "==============================" << endl;
for (itr = vi.begin(); itr != vi.end(); ++itr)
{
cout << *itr << endl;
}
return 0;
}
运行结果:
对象像函数一样使用。