STL 函数对象
1,重载函数调用操作符
函数对象:定义了调用操作符的类,其对象称为“函数对象”
STL中有大量的算法,这些算法是对SLT中的容器进行操作,算法需要函数对象作为参数因此使用STL算法的时候需要写函数对象。由于STL中的算法和容器都是用模板设计出来的,因此我们在写函数对象时也需要使用模板。
函数对象相较于普通函数的优势在于,函数对象的定义本身是一个类,而类可以有数据成员,来保持自身状态,这是普通的函数不具备的功能。
2,函数对象的声明与使用
普通模板函数
template<typename elementType> void FuncDisplayElement(const elementType & element) { cout << element << ' '; }
函数对象 :使用
struct
的原因:默认为public,而class
中需要声明//这也是一个类, 它声明的对象就是函数对象 struct absInt { //重载操作符:函数调用操作符 int operator() (int val) { return val < 0 ? -val : val; } }; //使用模板 template<typename elementType> struct DisplayElement { //存储状态 int m_nCont; DisplayElement() // 构造函数,初始化类中的变量 { m_nCont = 0; } void operator() (const elementType & element) { ++m_nCont; //这里比普通的函数对象就多了一个计数调用了函数多少次的功能 cout << element << ' '; } };
使用
/*普通函数对象的声明与使用*/ int i = -42; absInt absObj; unsigned int ui = absObj(i); /*STL中的函数对象与使用*/ vector<int> a; for (int i = 0; i < 10; ++i) a.push_back(i); //初始化一个vector DisplayElement<int> mResult; //声明一个函数对象 mResult = for_each(a.begin(), a.end(),mResult);//将状态通过for_each的返回值赋值保留到mResult中 cout << endl; cout << "number:" << mResult.m_nCont <<endl; //STL算法: //for_each算法:将处理前两个参数之间的所有数据,最后一个参数则为函数对象
匿名对象的使用
for_each(b.begin(), b.end(),DisplayElement<char>()); //DisPlayElement在函数中直接使用的叫做匿名对象,匿名函数对象无法操作和得到其状态
for_each()
算法 :将处理前两个参数之间的所有数据,最后一个参数是指定的pred运算条件(用函数对象表示)
2,一元谓词
函数只有一个参数,称为一元函数。函数对象只有一个参数,且返回值为布尔值时,为一元谓词。
函数 :写一个函数,检查是否为某一个数的整数倍
template<typename numberType> struct IsMultiple //检查是否为某数的整数倍 { numberType m_Divisor; //被除数由a传递而来,这里传过来为3 IsMultiple(const numberType & divisor) //构造函数 { m_Divisor = divisor; } bool operator() (const numberType & element) const { return ((element % m_Divisor) == 0); } };
初始化一个向量作为操作数
vector<int> vecIntegers; for (int i = 32; i < 101; ++i) { vecIntegers.push_back(i); }
find_if()
算法 :根据指定的pred运算条件(以仿函数表示),循环查找[first,last)内的所有元素,找出第一个令pred运算结果true者。如果找到就返回一个InputIterator指向该元素,否则就返回迭代器lastvector<int>::iterator iElement; IsMultiple<int> a(4); iElement = find_if(vecIntegers.begin(), vecIntegers.end(), a); // iElement = find_if(vecIntegers.begin(), vecIntegers.end(), IsMultiple<int>(4)); //匿名函数对象的使用 if (iElement != vecIntegers.end()) cout << "第一个四的整数倍是:" << *iElement << endl;
3,二元函数
函数对象有两个参数,称为二元函数,函数对象有两个参数,且返回值为布尔值时,为二元谓词。
二元函数示例 :创建一个类,来计算2个数的乘积。
template<typename elementType> class CMultiply //乘法 { public: elementType operator() (const elementType & elem1, const elementType & elem2) { return elem1 * elem2; } };
初始化两个向量a,b,初始化存放乘积结果的mResult
vector<int> a, b; for (int i = 0; i < 10; ++i) a.push_back(i); for (int i = 100; i < 110; ++i) b.push_back(i); vector<int> vecResult; vecResult.resize(10); //resize函数,分配空间让它与a,b一样大
transform()
函数:transform(a.begin(), a.end(),b.begin(), vecResult.begin(), CMultiply<int>()); //transform的前两个参数指定了循环的范围,根据指定的运算方式与第三个参数运算,结果存到第四个参数中 for (size_t i = 0; i < vecResult.size(); ++i) cout << vecResult[i] << endl;
4,二元谓词
创建函数 :这里注意,这里的函数中的两个参数,一个是set集中本就有的,另一个是新插入的。根据这两个参数的大小来返回布尔值,以达到不区分大小写的目的
//set中的string默认区分大小写 //这里使用二元谓词实现不区分大小写查找对应字符串 class CCompareStringNoCase { public: bool operator() (const string & str1, const string & str2) const { string str1LowerCase; str1LowerCase.resize(str1.size()); //新构建一个字符串保存备份并转化为小写字母 transform(str1.begin(), str1.end(),str1LowerCase.begin(),::tolower); //transform函数,将字符串都转化为小写字母 string str2LowerCase; str2LowerCase.resize(str1.size()); //新构建一个字符串保存备份并转化为小写字母 transform(str2.begin(), str2.end(), str2LowerCase.begin(),::tolower); //transform函数,将字符串都转化为小写字母 return(str1LowerCase < str2LowerCase); } };
声明变量并插入数值
set<string,CCompareStringNoCase> names; names.insert("Tina"); names.insert("jim");
使用
find()
函数 :查找set中的对应数据set<string, CCompareStringNoCase>::iterator iNameFound = names.find("tina"); if(iNameFound != names.end()) cout << "success " << *iNameFound << endl; else cout << "fail" << endl;