C++STL标准库学习笔记函数对象

Posted AwakeFantasy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++STL标准库学习笔记函数对象相关的知识,希望对你有一定的参考价值。

前言:

  在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来。

  在这一篇文章中,我们主要对STL中的函数对象进行简单的介绍。

正文:

1. 函数对象

  若一个类重载了运算符“()”,则该类的对象就成为函数对象

  例1:

 #include<iostream>
 using namespace std;
 
 class CMyAverage
 //函数对象类
     public:
     double operator()(int a1,int a2,int a3)
     
         return (double)(a1+a2+a3)/3;
     
 ;
 
 int main(int argc, char const *argv[])
 
     CMyAverage average;//函数对象
     cout<<average(3,2,3);//等价于average.operator()(3,2,3)
     //输出:2.66667
     return 0;
 

例2:

 #include<iostream>
 #include<vector>
 #include<algorithm>
 #include<numeric>
 #include<functional>
 using namespace std;
 
 int sumSquares(int total, int value)
 
     return total + value*value;
 
 
 template<class T>
 void PrintInterval(T first, T last)
 //输出区间[first, last)中的元素
     for (; first != last; ++first)
     
         cout<<*first<<" ";
     
     cout<<endl;
 
 
 template<class T>
 class SumPowers
 
     private:
     int power;
     public:
     SumPowers(int p):power(p)
     const T operator()(const T & total, const T & value)
     //计算value的power次方,加到total上
         T v = value;
         for (int i = 0; i < power-1; i++)
         
             v = v * value;
         
         return total + v;
     
 ;
 
 int main(int argc, char const *argv[])
 
     const int SIZE = 10;
     int a1[] = 1,2,3,4,5,6,7,8,9,10;
     vector<int> v(a1,a1+SIZE);
     cout<<"1)";
     PrintInterval(v.begin(),v.end());
     int result = accumulate(v.begin(),v.end(),0,sumSquares);
     //求出v上面所有元素的平方和
     cout<<"2)平方和"<<result<<endl;
     result = accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
     //SumPowers<int>(3)中,这是一个对象,其中power = 3
     //求出v上面所有元素的立方和
     cout<<"3)立方和"<<result<<endl;
     result = accumulate(v.begin(),v.end(),0,SumPowers<int>(4));
     cout<<"4)4次方和"<<result<<endl;
     return 0;
 
 /*
 输出:
 1)1 2 3 4 5 6 7 8 9 10 
 2)平方和385
 3)立方和3025
 4)4次方和25333
 */

  其中:

  在int result = accumulate(v.begin(),v.end(),0,SumSquares)

  这段代码中,实例化出:

 int accumlate(vector<int>::iterator first, vector<int>::iterator last, int init, int(*op)(int,int))
 
     for (; first != last; ++first)
     
         init = op(init,*first);
     
     return init;
 

  而在accumulate(v.begin(),v.end(),0,SumPowers<int>(3));

  实例化出:

 int accumlate(vector<int>::iterator first, vector<int>::iterator last, int init, SumPowers<int>op)
 
     for (; first != last; ++first)
     
         init = op(init,*first);
     
     return init;
 

  函数对象的价值:

  在刚刚的例子中,假使我们要求一个数组的1,2,3,4,5,6,7,8,9....次方和,如果不使用函数对象的话,就要可能要写n多个函数(虽然老师是这样说的,但是我传进去一个参数来知道做几次方不好吗,不过从这个例子中看,accumulate支持的函数似乎只支持两个参数传入,一个init,一个value,这种情况看来还是得用函数对象)

2. STL中的函数对象类模板

  以下模板可以用来生成函数对象。

  equal_to

  greater

  less

  ......

  它们都是模板而且也实现了“()”这个成员函数

  都在头文件:<functional>里定义了

  如:

 template<class T>
 struct greater:public binary function<T,T,bool>
 
     bool operator()(const T&x,const T&y)const
     
         return x > y;
     
 ;

3. greater的应用

  list有两个sort成员函数

  void sort();

    将list中的元素按“<”规定的比较方法升序排列。

  template<class Compare>

  void sort(Compare op)

  将list中的元素按op规定的比较方法升序排序。即要比较x,y大小时,看op(x,y)的返回值,为true则认为x小于y

  样例:

 #include<list>
 #include<iostream>
 using namespace std;
 
 class myless
 
 
 public:
     bool operator()(const int & c1, const int & c2)
     
         return (c1 % 10)<(c2 % 10);//比较个位数大小
     
 ;
 template<class T>
 void Print(T first, T last)
 
     for (; first != last; ++first)
     
         cout<<*first<<",";
     
     
 
 
 int main(int argc, char const *argv[])
 
     const int SIZE = 5;
     int a[SIZE] = 5,21,14,2,3;
     list<int> lst(a,a+SIZE);
     lst.sort(myless());
     Print(lst.begin(),lst.end());
     cout<<endl;//输出:21,2,3,14,5,
     lst.sort(greater<int>());//greater<int>()是个对象
     Print(lst.begin(),lst.end());
     cout<<endl;//输出:21,14,5,3,2,
     return 0;
 

  这个没有什么特别需要强调的。

4. 在STL中使用自定义的“大”“小”关系

  关联容器和STL中许多算法,都是可以用函数或函数对象自定义比较器的。在自定义了比较器op的情况下,以下三种说法是等价的:

  1)x小于y

  2)op(x,y)返回值为true

  3)y大于x

5. 例题:写出MyMax模板

 #include<iostream>
 #include<iterator>
 using namespace std;
 
 class MyLess
 
 public:
     bool operator()(int a1, int a2)
     
         if((a1%10)<(a2%10))
         
             return true;
         
         else
         
             return false;
         
     
 ;
 
 bool Mycompare(int a1, int a2)
 
     if((a1%10)<(a2%10))
     
         return false;
     
     else
     
         return true;
     
     
 
 
 template<class T, class Pred>
 T MyMax(T first, T last, Pred myless)
 
     T tmpMax = first;
     for (; first != last; ++first)
     
         if (myless(*tmpMax, *first))
         
             tmpMax = first;
         
         
     
     return tmpMax;
 
 
 int main(int argc, char const *argv[])
 
     int a[] = 35,7,13,19,12;
     cout<<*MyMax(a,a+5,MyLess())<<endl;//输出:19
     cout<<*MyMax(a,a+5,Mycompare)<<endl;//输出:12
     return 0;
 

后记:

到了这一节就感觉内容抽象了许多,但是c++对这些东西(指函数里面套函数)的支持还是让人感觉很惊喜的。

以上是关于C++STL标准库学习笔记函数对象的主要内容,如果未能解决你的问题,请参考以下文章

C++STL标准库学习笔记multiset

C++STL标准算法库的学习笔记

STL标准库 & 范型编程学习笔记:OOP(面向对象编程)与 GP(范型编程)容器之间的实现与分类

STL标准库 & 范型编程学习笔记:OOP(面向对象编程)与 GP(范型编程)容器之间的实现与分类

C++ STL 相关 部分笔记

STL标准库 & 范型编程学习笔记:C++学习网站STL六大部件介绍