目录
1.函数对象
1.1函数对象特点
2.谓词
2.1一元谓词
2.2二元谓词
3.内建函数对象
3.1算术仿函数
3.2关系仿函数
3.3逻辑仿函数
4.函数适配器
5.取反适配器
5.1一元取反适配器
5.2二元取反适配器
6.函数指针适配器
7.成员函数适配器
1.函数对象
概念:重载函数调用操作符的类,其对象称为函数对象
函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:函数对象(仿函数)是一个类对象,不是一个函数
1.1函数对象特点
- 函数对象可以有自己的状态;
- 可以作为参数传递。
2.谓词
概念:返回bool类型的仿函数或普通函数称为谓词
若仿函数或函数参数只有一个,那么是一元谓词
若仿函数或函数参数有两个,那么是二元谓词
2.1一元谓词
//创建仿函数
class GreaterFive
{
public:
bool operator()(int val)
{
return val > 5;
}
};
//向vector中增加10个数据
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//查找vector中大于5的数的位置
vector<int>::iterator result = find_if(v.begin(), v.end(), GreaterFive());
2.2二元谓词
//定义仿函数,降序排序
class MySort
{
public:
bool operstor(int v1, int v2)
{
return v1 > v2;
}
};
//向vector中塞五个数据
vector<int> v;
for (int i = 0; i < 5; i++)
{
v.push_back(i);
}
//把vector中的数据按照降序排列
sort(v.begin(), v.end(), MySort());
3.内建函数对象
概念:STL内建了一些函数对象,可以直接使用,需要引入#include<functional>,内建函数对象和普通函数对象用法一样
内建函数对象分类:
- 算术仿函数
- 关系仿函数
- 逻辑仿函数
3.1算术仿函数
算术仿函数实现的是四则运算,negate是一元运算,其他都是二元运算
仿函数原型:
negate<int> n;
cout << n(10);//取反,输出-10
plus<int> p;
cout << p(10, 20);//10+20=30,输出30
3.2关系仿函数
关系仿函数实现关系对比
仿函数原型:
//向vector中塞五个数据
vector<int> v;
for (int i = 0; i < 5; i++)
{
v.push_back(i);
}
//把vector中的数据按照降序排列
sort(v.begin(), v.end(), greater<int>());
3.3逻辑仿函数
逻辑仿函数实现逻辑运算
4.函数适配器
适配器:让原本接口不兼容的类可以合作无间
//仿函数,输出数值
class MyOut
{
void operator()(int num)
{
cout << num << endl;
}
};
void test01()
{
//数组里塞十个数
vector<int> v;
for (int i = 1; i < 10; i++)
{
v.push_back(i);
}
//利用仿函数遍历数组
for_each(v.begin(), v.end(), MyOut());
}
函数适配器使用步骤:
- 绑定bind2nd(将函数对象和参数绑定起来)
- 继承binary_function<参数类型1,参数类型2,返回值类型>
- 加const,让operator()变为常函数
注意:
- bind1st将绑定的参数作为operator()中的第一个参数
- bind2nd将绑定的参数作为operator()中的第二个参数
//继承binary_function<参数类型1,参数类型2,返回值类型>
class MyOut:public binary_function<int,int,void>
{
//加const,让operator()变为常函数
void operator()(int num, int start) const
{
cout << num + start << endl;
}
};
void test01()
{
//数组里塞十个数
vector<int> v;
for (int i = 1; i < 10; i++)
{
v.push_back(i);
}
cout << "请输入起始值";
int start;
cin >> start;
//绑定bind2nd
for_each(v.begin(), v.end(), bind2nd(MyOut(),start));
}
5.取反适配器
5.1一元取反适配器
//仿函数,找出第一个大于5的数
class MyOperator
{
public:
bool operator()(int a)
{
return a > 5;
}
};
//数组里塞十个数
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//返回数组中第一个大于5的数的位置
vector<int>::iterator it = find_if(v.begin(), v.end(), MyOperator());
一元取反适配器操作步骤:
- not1取反
- 继承unary_function<参数类型,返回值类型>
- 加const变为常函数
//一元取反适配器
//继承unary_function<参数类型,返回值类型>
class MyOperator:public unary_function<int,bool>
{
public:
//加const变为常函数
bool operator()(int a) const
{
return a > 5;
}
};
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//not1取反,返回小于5的数的位置
vector<int>::iterator it = find_if(v.begin(), v.end(), not1(MyOperator()));
5.2二元取反适配器
二元取反适配器操作步骤:not2
//回调函数,输出数字
void myPrint(int a)
{
cout << a << endl;
}
void test02()
{
//数组里塞十个数
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//升序,not2降序排列
sort(v.begin(), v.end(), not2(less<int>()));
//回调函数输出数字
for_each(v.begin(), v.end(), myPrint);
}
6.函数指针适配器
作用:ptr_fun将函数指针适配成函数对象
//回调函数,输出数字加上起始累加数字
void myPrint(int num,int start)
{
cout << num + start << endl;
}
void test02()
{
//数组里塞十个数
vector<int> v;
for (int i = 1; i < 10; i++)
{
v.push_back(i);
}
cout << "请输入起始值";
int start;
cin >> start;
//利用ptr_fun将函数指针适配成函数对象
for_each(v.begin(), v.end(), bind2nd(ptr_fun(myPrint),start));
}
7.成员函数适配器
mem_func是将成员函数入口地址,适配成全局函数
注意:
- 若容器中存放的是对象,成员函数适配器用mem_func_ref
- 若容器中存放的是对象指针,成员函数适配器用mem_func
class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}
//成员函数
void showPerson()
{
cout << m_name << endl;
cout << m_age;
}
string m_name;
int m_age;
};
//全局函数
void showPerson(Person& p)
{
cout << p.m_name << endl;
cout << p.m_age;
}
void test03()
{
//创建有5个Person的vector
vector<Person> VP;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
Person p5("eee", 50);
VP = { p1,p2,p3,p4,p5 };
//利用全局函数输出对象信息
for_each(VP.begin(), VP.end(), showPerson);
//利用成员函数输出对象信息
for_each(VP.begin(), VP.end(), mem_fun_ref(&Person::showPerson));
}