1 函数对象
- 函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)的方式使用一个类对象。
- 使用STL中提供的或自定义的迭代器和**函数对象,**配合STL的算法,组合出各种各样的功能。
- 通过函数对象而不使用函数指针,可以增加通用性,提高效率。为什么使用函数对象
- 函数对象概念:泛化的函数
①将普通函数作为函数对象:传递函数名
#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
using namespace std;
int mult(int a, int b) {
return a * b;
}
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7 };
const int N = sizeof(a) / sizeof(int);
cout << "所有数累乘为:" << accumulate(a, a + N, 1, mult) << endl;
return 0;
}
②将重载了()运算符的类的对象作为函数对象:传递"类名()"
#include <numeric>
#include <iostream>
using namespace std;
class MultClass {
public:
int operator () (int a, int b) const {
return a * b;
}
};
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7 };
const int N = sizeof(a) / sizeof(int);
cout << "所有数乘积为:" << accumulate(a, a + N, 1, MultClass()) << endl;
MultClass ss;
cout << ss(100, 100);
return 0;
}
2 STL提供的函数对象
1.系统提供函数对象帮助实现基本功能。 2.accmulate算法接受二元函数对象,transform算法接受一元函数对象。 ①STL库的multiplies
#include <iostream>
#include <functional>
#include <numeric>
using namespace std;
int main(){
int a[] = { 1, 2, 3, 4, 5, 6, 7 };
const int N = sizeof(a) / sizeof(int);
cout << accumulate(a, a + N, 1, multiplies<int>()) << endl;
return 0;
}
②STL库的二元谓词greater
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main() {
int arr[] = { 24, 43, 5, 4, 62, 34, 7654, 22 };
const int N = sizeof(arr) / sizeof(int);
copy(arr, arr + N, ostream_iterator<int>(cout, "\t"));
cout << endl;
sort(arr, arr + N, greater<int>());
copy(arr, arr + N, ostream_iterator<int>(cout, "\t"));
return 0;
}
3 函数适配器
适配器顾名思义,让函数适配算法。 Unary Predicate:一元谓词 binary:二元的 bind:结合,(使)联合在一起
①找出第一个大于40的数,注意用数组和vector都可以
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main()
{
int a[] = { 30, 40, 50, 90, 20, 10 };
const int N = sizeof(a) / sizeof(int);
int *c = find_if(a, a + N, bind2nd(greater<int>(), 40));
cout << *c << endl;
return 0;
}
一般使用数组初始化向量vector,后续操作更方便
int main()
{
int a[] = { 30, 40, 50, 90, 20, 10 };
const int N = sizeof(a) / sizeof(int);
vector<int> v (a, a + N);
vector<int>::iterator p = find_if (v.begin(), v.end(), bind2nd(greater<int>(), 40) );
if (p == v.end())
cout << "找不到" << endl;
else
cout << *p << endl;
return 0;
}
find_if算法在STL中的原型声明为:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if(InputIterator first, InputIterator last, UnaryPredicate pred);
它的功能是查找数组[first, last)区间中第一个pred(x)为真的元素。
InputIterator、UnaryPredicate是用概念来做模板参数名
②利用prt_fun、not1、not2产生组合适配器
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;
int g(int x, int y) {
return x > y;
}
int main()
{
int a[] = { 30, 90, 10, 23, 432, 656, 7, 78 };
const int N = sizeof(a) / sizeof(int);
vector<int> v(a, a + N);
auto p1 = find_if(v.begin(), v.end(), bind2nd(ptr_fun(g), 40));
if (p1 == v.end())
cout << "no element" << endl;
else
cout << *p1 << endl;
auto p2 = find_if(v.begin(), v.end(), not1(bind2nd(ptr_fun(g), 15)));
if (p2 == v.end())
cout << "no element" << endl;
else
cout << *p2 << endl;
auto p3 = find_if(v.begin(), v.end(), bind2nd(not2(ptr_fun(g)), 15));
if (p3 == v.end())
cout << "no element" << endl;
else
cout << *p3 << endl;
return 0;
}
③成员函数适配器,类的成员函数要通过适配器转换为普通函数对象
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
struct Car
{
int id;
Car(int id) {
this->id = id;
}
void display() const {
cout << "car " << id << endl;
}
};
int main() {
vector<Car*> pcars;
vector<Car> cars;
for (int i = 0; i < 5; i++)
pcars.push_back(new Car(i));
for (int i = 5; i < 10; i++)
cars.push_back(Car(i));
cout << "elements in pcars: " << endl;
for_each(pcars.begin(), pcars.end(), mem_fun(&Car::display));
cout << endl;
for_each(cars.begin(), cars.end(), mem_fun_ref(&Car::display));
cout << endl;
for (size_t i = 0; i < pcars.size(); ++i)
delete pcars[i];
return 0;
}
为什么不能同全局函数一样直接传递函数名而成员函数必须以 &类名::函数名 的方式,因为需要考虑static成员函数的情况。 mem_fun(member适配为function):将成员函数适配为普通函数对象,适配出来的函数需要对象的指针作为参数。 men_fun_ref:将成员函数适配为普通函数对象,适配出来的函数需要对象的引用作为参数。
|