[C.C++] C++仿函数

110 0
Honkers 昨天 12:47 来自手机 | 显示全部楼层 |阅读模式

     仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类。该类重载了operator()运算符,调用仿函数的时候实际上就是通过类对象调用重载后的operator操作符,重载operator()和重载普通的函数效果相同,当参数类型不同时会执行不同的代码逻辑。让类型可以模仿函数调用的行为: 函数名(参数); 类名() 调用的函数行为。

    有时仿函数的使用是为了函数拥有类的性质,以达到安全传递函数指针,依据函数生成对象,甚至是让函数之间有继承关系,对函数进行运算和操作的效果。比如set就使用了仿函数less ,而less继承的binary_function,就可以看作是对于一类函数的总体声明了,这是函数做不到的。

   仿函数还给出了static的替代方案,函数内的静态变量可以改成类的私有成员,这样可以明确地在析构函数中清除所用的内容,如果用到了指针,那么这个是不错的选择。有人说这样的类已经不是仿函数了,但其实,封装后从外界观察,可以明显地发现,它依然有函数的性质。

面向对象能够减少代码的耦合性,同样仿函数也沾了class的光。比如,一个dfs()函数,调用的时候要传入位置、深度两个值。从外部观察,dfs(x,1)的语句中,1的意义并不明确,从实际来讲,也的确没有传入的必要,甚至可能导致错误。

1、void dfs(int x,int deep=1){...}这样的话,虽然dfs(x)变成了可用语句,但你不能要求每个调用它的人都只传一个参。如果有人写dfs(x,-9999),可能会导致运行错误。

2、void dfs2(int x,int deep){}void dfs(int x){dfs2(x,1);}同样dfs(x)也是可用的,但是如果另一个使用者并不知道dfs与dfs2的区别,写了dfs2(x,-1)还是有风险

3、namespace 某个名字{void dfs2(int x,int deep){...}}void dfs(int x){某个名字::dfs2(x,1);}这样已经不错了,但是namespace的意义不明,其它使用者看到大纲估计会在心中把你千刀万剐。

4、使用仿函数,把dfs()写成仿函数,把2中的dfs2变成它的私有成员函数,这样不会有意义不明的东西出现,也能实现安全调用,从外部看,这就是一个可以"生活自理"、有"独立意识"函数了。

 

       C++标准库中的仿函数存在在于functional.h中,平时用到的最多的是greater,less这两个,这两个函数常被用做排序函数的参数。

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <functional>
  4. using namespace std;
  5. class Data
  6. {
  7. public:
  8. //operator()组成函数名
  9. void operator()()
  10. {
  11. cout << "无参重载()" << endl;
  12. }
  13. void operator()(int a, int b)
  14. {
  15. cout << "有参重载(a,b)" << endl;
  16. //也可以对a,b进行操作
  17. }
  18. protected:
  19. };
  20. int main()
  21. {
  22. greater<int>(); //比较准则
  23. int array[5] = { 3,4,1,2,32 };
  24. sort(array, array + 5, greater<int>());
  25. // 遍历容器元素注意:
  26. //for(auto x : v)会创建v中元素的拷贝赋给x,所以如果在for循环体内修改x,是不会影响到v的。
  27. //如果想避免拷贝的话,可以这么写:for(auto & x : v)
  28. //如果只想读v中的元素,但不想修改v的话,可以这么写:for(const auto & x : v)
  29. for (auto& v : array)
  30. {
  31. cout << v << "\t";
  32. }
  33. cout << endl;
  34. Data data;
  35. data.operator()(); //显式调用
  36. data.operator()(1, 2); //显式调用
  37. data(); //隐式调用
  38. data(1, 2); //隐式调用
  39. Data{}(); //{}帮助识别 Data()
  40. Data{}(2, 3);
  41. return 0;
  42. }
复制代码

 

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行