C++STL标准库学习笔记(十一)函数对象


前言:

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

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

正文:

1. 函数对象

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

  例1:

 1 #include
 2 using namespace std;
 3 
 4 class CMyAverage
 5 {//函数对象类
 6     public:
 7     double operator()(int a1,int a2,int a3)
 8     {
 9         return (double)(a1+a2+a3)/3;
10     }
11 };
12 
13 int main(int argc, char const *argv[])
14 {
15     CMyAverage average;//函数对象
16     cout<3,2,3);//等价于average.operator()(3,2,3)
17     //输出:2.66667
18     return 0;
19 }

例2:

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 using namespace std;
 7 
 8 int sumSquares(int total, int value)
 9 {
10     return total + value*value;
11 }
12 
13 template<class T>
14 void PrintInterval(T first, T last)
15 {//输出区间[first, last)中的元素
16     for (; first != last; ++first)
17     {
18         cout<<*first<<" ";
19     }
20     cout<<endl;
21 }
22 
23 template<class T>
24 class SumPowers
25 {
26     private:
27     int power;
28     public:
29     SumPowers(int p):power(p){}
30     const T operator()(const T & total, const T & value)
31     {//计算value的power次方,加到total上
32         T v = value;
33         for (int i = 0; i < power-1; i++)
34         {
35             v = v * value;
36         }
37         return total + v;
38     }
39 };
40 
41 int main(int argc, char const *argv[])
42 {
43     const int SIZE = 10;
44     int a1[] = {1,2,3,4,5,6,7,8,9,10};
45     vector<int> v(a1,a1+SIZE);
46     cout<<"1)";
47     PrintInterval(v.begin(),v.end());
48     int result = accumulate(v.begin(),v.end(),0,sumSquares);
49     //求出v上面所有元素的平方和
50     cout<<"2)平方和"<endl;
51     result = accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
52     //SumPowers(3)中,这是一个对象,其中power = 3
53     //求出v上面所有元素的立方和
54     cout<<"3)立方和"<endl;
55     result = accumulate(v.begin(),v.end(),0,SumPowers<int>(4));
56     cout<<"4)4次方和"<endl;
57     return 0;
58 }
59 /*
60 输出:
61 1)1 2 3 4 5 6 7 8 9 10 
62 2)平方和385
63 3)立方和3025
64 4)4次方和25333
65 */

  其中:

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

  这段代码中,实例化出:

1 int accumlate(vector<int>::iterator first, vector<int>::iterator last, int init, int(*op)(int,int))
2 {
3     for (; first != last; ++first)
4     {
5         init = op(init,*first);
6     }
7     return init;
8 }

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

  实例化出:

1 int accumlate(vector<int>::iterator first, vector<int>::iterator last, int init, SumPowers<int>op)
2 {
3     for (; first != last; ++first)
4     {
5         init = op(init,*first);
6     }
7     return init;
8 }

  函数对象的价值:

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

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

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

  equal_to

  greater

  less

  ......

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

  都在头文件:里定义了

  如:

1 template<class T>
2 struct greater:public binary functionbool>
3 {
4     bool operator()(const T&x,const T&y)const
5     {
6         return x > y;
7     }
8 };

3. greater的应用

  list有两个sort成员函数

  void sort();

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

  template

  void sort(Compare op)

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

  样例:

 1 #include
 2 #include
 3 using namespace std;
 4 
 5 class myless
 6 {
 7 
 8 public:
 9     bool operator()(const int & c1, const int & c2)
10     {
11         return (c1 % 10)<(c2 % 10);//比较个位数大小
12     }
13 };
14 template<class T>
15 void Print(T first, T last)
16 {
17     for (; first != last; ++first)
18     {
19         cout<<*first<<",";
20     }
21     
22 }
23 
24 int main(int argc, char const *argv[])
25 {
26     const int SIZE = 5;
27     int a[SIZE] = {5,21,14,2,3};
28     list<int> lst(a,a+SIZE);
29     lst.sort(myless());
30     Print(lst.begin(),lst.end());
31     cout<//输出:21,2,3,14,5,
32     lst.sort(greater<int>());//greater()是个对象
33     Print(lst.begin(),lst.end());
34     cout<//输出:21,14,5,3,2,
35     return 0;
36 }

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

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

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

  1)x小于y

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

  3)y大于x

5. 例题:写出MyMax模板

 1 #include
 2 #include
 3 using namespace std;
 4 
 5 class MyLess
 6 {
 7 public:
 8     bool operator()(int a1, int a2)
 9     {
10         if((a1%10)<(a2%10))
11         {
12             return true;
13         }
14         else
15         {
16             return false;
17         }
18     }
19 };
20 
21 bool Mycompare(int a1, int a2)
22 {
23     if((a1%10)<(a2%10))
24     {
25         return false;
26     }
27     else
28     {
29         return true;
30     }
31     
32 }
33 
34 template<class T, class Pred>
35 T MyMax(T first, T last, Pred myless)
36 {
37     T tmpMax = first;
38     for (; first != last; ++first)
39     {
40         if (myless(*tmpMax, *first))
41         {
42             tmpMax = first;
43         }
44         
45     }
46     return tmpMax;
47 }
48 
49 int main(int argc, char const *argv[])
50 {
51     int a[] = {35,7,13,19,12};
52     cout<<*MyMax(a,a+5,MyLess())<//输出:19
53     cout<<*MyMax(a,a+5,Mycompare)<//输出:12
54     return 0;
55 }

后记:

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

相关