适配器
函数对象适配器
前提引入:
class MyPrint
{
public:
//原先只有val,但是想在val的基础上加上可以自定义的start
void operator()(int val,int start)
{
cout << val + start << endl;
}
};
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), MyPrint());//注意,仿函数放进去的是匿名对象
//for_each的底层是从范围内开始遍历,然后依次进行解引用,每次返回一个数,然后将这个数传进后面的仿函数中。
//但是如果仿函数中打印的数字发生了变化(从一个数变成了两个数的相加),那么原先返回的一个数就不够传参,需要再传一个参数。所以需要将另一个数创建出来,并与MyPrint()进行合并
return 0;
}
进行改变:
1,利用bind2nd进行绑定
2,继承:public binary_function<参数1类型,参数2类型,返回值类型> —这个是二元继承的父类
3,加const,下面重载的()的函数已经是在继承的父类中写好的,子类中进行重写的状态是只读。
class MyPrint:public binary_function<int,int,void>//进行继承
{
public:
void operator()(int val,int start)const
{
cout << val + start << endl;
}
};
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
int num;
cin >> num;
for_each(v.begin(), v.end(), bind2nd(MyPrint(),num));//通过bind2nd将仿函数和另一个自定义的参数绑定。
//注意,这里的bind1st是将传进来的num参数作为第一个参数传入仿函数中,而bind2nd是作为第二参数传入。
return 0;
}
完成了适配器的功能,将仿函数的参数从一个适配成了两个。
取反适配器
一元取反
前提引入:
如果想在存有0-9的容器中找到一个大于5的数,可以使用find_if函数从容器的开始到结尾进行遍历寻找,传入GreaterThanFive()的仿函数进行寻找,然后就会返回6。这时如果想返回一个小于5的数,那么可以直接通过修改仿函数中的>为<就可以找到。也可以通过使用适配器的功能。
进行改变:
1,使用not1进行取反
2,继承:public unary_function<int,bool> —这个是一元继承
3,加const
class GreaterThanFive :public unary_function<int,bool>
{
public:
bool operator()(int val) const//返回值是bool类型
{
return val > 5;
}
};
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>::iterator pos = find_if(v.begin(), v.end(), not1(GreaterThanFive()));//find_if的返回值类型是迭代器
//还有一种写法:直接使用内建函数对象(这样就不用再自己写仿函数了),使用一个内建函数对象(bind2nd)加一个数字表示大于这个数字
//vector<int>::iterator pos = find_if(v.begin(),v.end(),not1(bind2nd(greater<int>(),5)));
//打印迭代器的数据
if (pos != v.end())
{
cout << *pos << endl;
}
else
{
cout << "没有找到" << endl;
}
return 0;
}
二元取反
前提引入:
将容器中的数据通过使用less< int >()的内建函数对象 改变为从大到小的排列
进行改变:
在排序中对内建函数对象进行适配器的调整,这里并不需要继承以及加const,因为不是自己写的类,在源代码中已经是操作过了,所以只需要在less< int >()前面加个not2即可。
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
sort(v.begin(), v.end(), not2(less<int>()));
//进行容器中数据的打印
for_each(v.begin(), v.end(), [](int val) {cout << val << endl; });
return 0;
}
函数适配器
前提引入:
将容器中的数据遍历,现在要求在遍历的基础上加1000,像上面的函数对象适配器一样。
void myPrint3(int val)
{
cout << val << endl;
}
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), myPrint3);//0123456789
return 0;
}
进行改变:
由于使用的是回调函数,而不是内建函数对象,所以也就不用自己写类的继承和const。但是需要将myPrint3这个函数指针变成函数对象,使用ptr_fun函数。然后再将这个函数对象与自定义的数字进行合并。
void myPrint3(int val,int start)//函数的参数由一个变成两个
{
cout << val + start<< endl;
}
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), bind2nd(ptr_fun(myPrint3),1000));
return 0;
}
成员函数适配器
前提引入:
将存放Person类数据的vector容器使用回调函数进行遍历(全局函数)。然后要求不使用回调函数,使用类中的成员函数进行遍历。
class Person
{
public:
Person(string name,int age)
{
this->m_age = age;
this->m_name = name;
}
string m_name;
int m_age;
};
void myPrint(Person&p)
{
cout << p.m_name << " " << p.m_age << endl;
}
int main()
{
vector< Person > v;
Person p1("a", 10);
Person p2("b", 20);
Person p3("c", 30);
Person p4("d", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
for_each(v.begin(), v.end(), myPrint);
return 0;
}
进行改变:
使用类中的成员函数实现遍历。首先需要获取到成员函数的地址,然后再使用mem_fun_ref将成员函数适配(可以理解为适配成全局函数了,和刚才的myPrint一样)
class Person
{
public:
Person(string name,int age)
{
this->m_age = age;
this->m_name = name;
}
string m_name;
int m_age;
void showPerson()
{
cout << this->m_name << " " << this->m_age << endl;
}
};
int main()
{
vector< Person > v;
Person p1("a", 10);
Person p2("b", 20);
Person p3("c", 30);
Person p4("d", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
for_each(v.begin(), v.end(), mem_fun_ref( & Person::showPerson));
return 0;
}
如果想让所有的这个类的对象都进行某个操作,那么就可以使用这种方法。
如果在这个基础上的所有年龄再加100
class Person
{
public:
Person(string name,int age)
{
this->m_age = age;
this->m_name = name;
}
string m_name;
int m_age;
void showPerson()
{
cout << this->m_name << " " << this->m_age << endl;
}
void ageAdd()
{
this->m_age += 100;
}
};
int main()
{
vector< Person > v;
Person p1("a", 10);
Person p2("b", 20);
Person p3("c", 30);
Person p4("d", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
for_each(v.begin(), v.end(), mem_fun_ref( & Person::showPerson));
for_each(v.begin(), v.end(), mem_fun_ref(&Person::ageAdd));//将容器中所有的Person对象的年龄加100
for_each(v.begin(), v.end(), mem_fun_ref(&Person::showPerson));//然后再进行一次打印
return 0;
}