C++STL标准库学习笔记(十一)函数对象
前言:
在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来。
在这一篇文章中,我们主要对STL中的函数对象进行简单的介绍。
正文:
1. 函数对象
若一个类重载了运算符“()”,则该类的对象就成为函数对象
例1:
1 #include2 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 #include2 #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
实例化出:
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 #include2 #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 #include2 #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++对这些东西(指函数里面套函数)的支持还是让人感觉很惊喜的。