#include<iostream>
using namespace std;
#include"algorithm" //算法的头文件
#include"functional" //同为算法的头文件
#include"set"
#include"vector"
#include"list"
#include"string"
//注意:!!!!一定要分得清楚算法的返回值是迭代器,还是谓词(函数对象)!!!!
//例如for_each()算法返回了一个函数对象
/*函数对象与普通函数以及模板函数的区别*/
//函数对象 重载了函数调用操作符 : ()
//类模板 实现
template<typename T> //这里是只有一个函数参数 是一元函数对象
class myClass
{
public:
myClass() //构造函数
{
// n = 0;
}
void printhM()
{
// cout <<"n ="<< n << endl;
}
void operator()(T a)
{
//n++;
//printhM();
cout << a << " " ;
}
public:
T n;
};
//普通函数
void printfM2(int a)
{
cout << "普通函数" << a << endl;
}
//函数模板
template<typename T>
void printfM1(T a)
{
cout << "函数模板"<<a << endl;
}
//函数对象与普通函数以及模板函数的区别
void main01()
{
int a;
a = 20;
myClass<int> showmyClass;
showmyClass.printhM();//调用成员函数
showmyClass(a); //函数对象 该类模板重载了()操作符,因此这里看起来非常类似于一个函数的调用
printfM1<int>(a); //函数模板的调用 采用显示调用法
printfM2(a); //普通函数的调用
}
//函数对象属于类对象,可以突破函数的概念, 保持调用状态信息
//函数对象的好处:
//for_each算法当中的参数
//for_each算法当中的返回值
void main02()
{
vector<int> m_vec;
m_vec.push_back(1);
m_vec.push_back(6);
m_vec.push_back(9);
for_each(m_vec.begin(), m_vec.end(), myClass<int>( )); //匿名函数对象 匿名仿函数
for_each(m_vec.begin(), m_vec.end(), printfM2); // 回调函数 实现了任务的编写者与任务的调用者的分离
//因为for_each算法当中,第三个参数是传入一个值,而不是引用,因此使用printhM()在for_each外打印时依旧为0
myClass<int> c_myclass;
for_each(m_vec.begin(), m_vec.end(), c_myclass); //不采用匿名函数
c_myclass.printhM();
//解决办法
//首先按F12观察原函数 发现返回一个函数_Func 因此用一个函数对象来接返回值便可以
/*template<class _InIt,
class _Fn1> inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Func);
_For_each(_Unchecked(_First), _Unchecked(_Last), _Func);
return (_STD move(_Func));
}*/
myClass<int> c_myclass_1;
c_myclass_1 = for_each(m_vec.begin(), m_vec.end(), c_myclass_1); //不采用匿名函数
c_myclass_1.printhM();
}
//一元谓词
template <typename T>
class Exp
{
public:
bool operator()(T a) //含有一个参数 并且返回一个bool类型的值
{
return (a % 4 == 0);
}
private:
int a;
};
//一元谓词 通过一元谓词判断一个数能否被4整除
void main03()
{
Exp<int> c_e;
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(16);
v1.push_back(4);
vector<int>::iterator it;
it=find_if(v1.begin(), v1.end(), Exp<int>()); //find_if 返回一个迭代器
if (it == v1.end())
{
cout << "没有数可以被4整除" << endl;
}
else
{
cout << "第一个能被4整除的数"<<*it << endl;
}
}
//二元函数对象 类中默认的访问为private struct中是public
template<typename T>
class ADD
{
public:
T operator()(T a, T b)
{
return a + b;
}
};
void main04()
{
vector<int> v1;
vector<int> v2;
vector<int> v3;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v2.push_back(2);
v2.push_back(4);
v2.push_back(6);
v3.resize(3); //重新设置vector的大小
transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), ADD<int>()); //匿名函数的二元函数对象
//transform 将运算结果的迭代器位置返回
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
cout << *it << endl;
}
}
//二元谓词 从大到小排列
bool funComplare(int a,int b)
{
return a > b;
}
void main05() //二元谓词 案例:实现对于一个vector的排序
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
int tmp = rand() % 100; //0-100的未知数
v1.push_back(tmp);
}
//采用 for_each 算法实现遍历
for_each(v1.begin(), v1.end(), myClass<int>());
//利用二元谓词实现排序
sort(v1.begin(),v1.end(), funComplare);
cout << endl;
//采用 for_each 算法实现遍历
for_each(v1.begin(), v1.end(), myClass<int>());
}
//实现二元谓词
struct withNocase
{
bool operator()(const string &strLeft, const string &strRight)
{
string strLeft_;
strLeft_.resize(strLeft.size());
transform(strLeft.begin(), strLeft.end(), strLeft_.begin(),tolower);
string strRight_;
strRight_.resize(strRight.size());
transform(strRight.begin(), strRight.end(), strRight_.begin(), tolower);
return (strRight_ < strLeft_);
}
};
void main06() //实现在set中的find函数的不区分大小写的查找
{
set<string> myset;
myset.insert("hkashdkj");
myset.insert("torres");
myset.insert("bob");
myset.insert("Abc");
//利用for_each 算法实现遍历
for_each(myset.begin(), myset.end(), myClass<string>());
set<string>::iterator it = myset.find("abc");
if (it != myset.end())
{
cout << "查找到该元素" << endl;
}
else
{
cout << "没有查到该元素" << endl;
}
cout << "----------------------" << endl;
set<string,withNocase> myset_;
myset_.insert("hkashdkj");
myset_.insert("torres");
myset_.insert("bob");
myset_.insert("Abc");
//利用for_each 算法实现遍历
for_each(myset_.begin(), myset_.end(), myClass<string>());
set<string, withNocase>::iterator it_ = myset_.find("abc");
if (it_ != myset_.end())
{
cout << "查找到该元素" << endl;
}
else
{
cout << "没有查到该元素" << endl;
}
}
void main()
{
//main01();//普通函数与函数模板的区别
//main02(); //函数对象属于类对象,可以突破函数的概念, 保持调用状态信息
//main03(); //一元谓词
//main04(); //二元函数对象
//main05(); //二元谓词
main06(); //二元谓词在set集合中的应用
system("pause");
}
C++ 有关于函数对象以及谓词部分练习以及知识点的总结
最新推荐文章于 2024-07-14 20:07:21 发布