1. 首页
  2. c++

你好,C++(71)11.1.3 将函数指针应用到STL算法中

想要抢先看后面的章节?打赏本文10元,即可获得带插图全本下载地址!
打赏完成记得私信我哦 :p

11.1.3 将函数指针应用到STL算法中

就像上文中介绍的mycount_if*()算法一样,对于STL中的大多数算法,特别是以if为后缀的算法,也可以通过给它们提供一个函数指针,对其中的核心业务逻辑进行自定义,以最终使得STL中的通用算法能够满足各种个性化的需求,做到真正地通用。例如,我们可以为STL中的count_if()算法提供一个指向统计规则函数的函数指针,让它统计容器中所有符合条件的数据的个数:

// 利用函数定义统计的规则,统计身高大于170的Student对象 bool countHeight( const Student& st ) {  // 如果身高大于170,则统计在内  return st.GetHeight() > 170; } // 将统计规则函数的指针countHeight应用到count_if()算法中 // 这样count_if()算法将调用countHeight()函数来判断数据是否符合条件 int nCount = count_if(vecStu.begin(), vecStu.end(), countHeight );  cout<<"身高大于170的学生有:"<<nCount<<endl;

在这段代码中,首先定义了一个函数countHeight(),并在其中表述了自己的统计规则:判断Student对象的身高是否大于170,如果大于,则返回true,表示当前数据统计在内。然后,将这个函数名,也就是指向这个函数的函数指针countHeight作为实际参数调用STL中的count_if()算法。当count_if()算法对容器中的数据进行统计时,会调用countHeight()函数来判断当前数据是否符合统计规则,如果符合则统计在内。换句话说,以函数指针的形式作为参数传递给count_if()算法的countHeight()函数成了一个回调函数,它会在count_if()算法中被调用。这样,可以在countHeight()函数中实现自己的统计规则,从而让count_if()算法按照自定义的规则进行统计,最终实现利用函数指针对STL算法进行自定义的目的。

从以上这段代码中我们也注意到,countHeight()函数中的标准身高已经固定下来,这就使得整个算法失去了一定得灵活性,如果要统计大于另外一个身高标准的人数,则不得不重新编写另外一个统计规则函数。为了让这个统计算法具有更大的灵活性,我们可以对统计规则函数countHeight()进行改写,将统计标准也作为函数的参数,在调用时再根据具体情况给定统计标准,让这个统计算法更加灵活:

// 将统计标准也作为参数,重新定义统计规则函数 bool countHeight( const int nHeight, const Student st ) {  // 如果身高大于标准身高,则统计在内  return st.GetHeight() > nHeight; }

而在调用count_if()算法进行统计时,就可以使用bind1st()函数动态地绑定它的第一个参数,也就是指定统计的身高标准,从而灵活地完成各种身高人数的统计:

// 待统计的容器 vector<Student> vecStu; // 用push_back()函数将Student对象添加到vecStu容器中… int nH = 0; // 身高标准 // 动态输入身高标准  cout<<"请输入身高标准"<<endl;  cin>>nH; // 利用countHeight()函数进行统计 // 同时动态指定nH作为它的第一个参数,设定身高标准 int nCount = count_if(vecStu.begin(), vecStu.end(), // 统计范围  bind1st( ptr_fun(countHeight),nH));  // 统计规则  cout<<"身高大于"<<nH<<"的人数是"<<nCount<<endl;

在这里,首先使用ptr_fun()函数将一个普通函数指针countHeight转换为一个函数对象[1],给函数换了一件马甲。同样,这个函数对象跟countHeight()函数一样也需要两个参数,但是count_if()算法要求它的规则函数只能有一个参数,所以我们得到函数对象后,用bind1st()函数将其第一个参数nHeight绑定为用户输入的nH,这样它就成了一个只拥有一个Student&类型参数的函数对象,从而可以直接用在count_if ()算法中。而在count_if()算法执行的时候,它会逐个使用容器中的数据作为参数调用这个函数对象,实际上也就是以nH和当前Stuent对象为参数调用countHeight()函数,从而判断这个对象是否需要统计在内。这样,即使用户输入的身高标准不同,我们也可以用相同的count_if()算法调用形式来完成统计。除了可以在STL算法中使用普通的函数指针,将容器中的数据作为参数传递给它所指向的函数进行处理之外,我们还可以在算法中使用指向类成员函数的指针,从而在算法处理过程中直接调用容器中数据的成员函数来实现功能。例如在前面的算法体育课中,为了让容器中的Student对象报数,我们先是利用for_each ()算法将Student对象传递给CountOff()函数,在这个函数中才间接地调用Student对象的Report()成员函数完成报数。报数的功能是实现了,但是过程有点繁琐,这显然不符合STL优雅的风格。实际上,利用指向类成员函数的指针,这个过程可以直接一步完成:

// 使用类成员函数指针调用容器中数据的成员函数 for_each(vecStu.begin(),vecStu.end(),   mem_fun_ref(&Student::Report)); // 调用Report()成员函数

在这里,首先使用“&”操作符获得Student类的成员函数Report()的地址,也就是获得了指向这个成员函数的函数指针。因为这里的Report()函数属于Student类,所以我们要在函数名之前用“::”加上类名;然后使用mem_fun_ref()函数将这个成员函数指针构造成一个函数对象。表面上看起来Report()成员函数没有参数,但每个类成员函数都有一个隐藏的参数,那就是指向它自身的指针。Report()成员函数指针经过mem_fun_ref()函数构造后的函数对象,就可以接受一个Student类型的对象为参数,因此可以直接应用到for_each()算法中。在执行的时候,当for_each()算法将容器中的Student对象作为参数传递给这个函数对象时,实际上就是调用这个Student对象的Report()成员函数,直接完成报数的的功能。这里需要注意的是,如果容器中保存的是指向对象的指针,就应该使用mem_fun()函数来完成这一任务。

将指向类成员函数的函数指针应用到STL算法中,让我们可以藉由数据自身的函数来完成对数据的处理,省去了中间环节,因而这一方式被广泛地应用在STL算法中。

[1] 函数的另外一种形式,它以实体对象来表示一个函数,我们将在稍后的章节中加以介绍。

原文始发于:你好,C++(71)11.1.3 将函数指针应用到STL算法中

主题测试文章,只做测试使用。发布者:杀手梦三刀,转转请注明出处:http://www.cxybcw.com/7648.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code