一、函数对象

1、函数对象(function object)也称为仿函数(functor)

2、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。
3、任何重载了调用运算符operator()的类的对象都满足函数对象的特征
4、函数对象可以把它称之为smart function。
5、STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。

二、自定义函数对象

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
#include <iostream>
using namespace std;
class CFunObj
{
public:
    void operator()()
    {
        cout << "hello,function object!" << endl;
    }
};
int main()
{
    CFunObj fo;
    fo();
    CFunObj()();
    return 0;
}

注意:CFunObj()(); 表示先构造一个匿名对象,再调用operator();

C++ Code 
1
2
3
4
5
6
7
8
9
10
 
// TEMPLATE CLASS map
template < class _Kty,
         class _Ty,
         class _Pr = less<_Kty>,
         class _Alloc = allocator<pair<const _Kty, _Ty> > >
class map
    : public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false> >
{
    // ordered red-black tree of {key, mapped} values, unique keys
};

假设现在我们这样使用 map< int, string > mapTest; 那么默认的第三个参数 _Pr = less<int>,再者,map 继承的其中一个类

_Tmap_traits 中有个成员:

_Pr  comp;// the comparator predicate for keys

跟踪进insert 函数,其中有这样一句:

if (_DEBUG_LT_PRED(this->comp, _Key(_Where._Mynode()), this->_Kfn(_Val)))

已知 #define _DEBUG_LT_PRED(pred, x, y) pred(x, y) 很明显地,comp 在这里当作函数对象使用,传入两个参数,回头看less 类的

模板实现:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
 
// TEMPLATE STRUCT less
template<class _Ty>
struct less
        : public binary_function<_Ty, _Ty, bool>
{
    // functor for operator<
    bool operator()(const _Ty &_Left, const _Ty &_Right) const
    {
        // apply operator< to operands
        return (_Left < _Right);
    }
};

即实现了operator() 函数,左操作数小于右操作数时返回为真。

我们也可以在定义的时候传递第三个参数,如map< int, string, greater<int> > mapTest; 则插入时按key 值从大到小排序(less,

greater 都是STL内置的类,里面实现了operator() 函数),甚至也可以自己实现一个类传递进去,如下面例程所示:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
#include <map>
#include <string>
#include <iostream>

using namespace std;

struct MyGreater
{
    bool operator()(int left, int right)
    {
        return left > right;
    }
};

int main(void)
{
    map < int, string, /*greater<int> */MyGreater > mapTest;
    mapTest.insert(map<int, string>::value_type(1, "aaaa"));
    mapTest.insert(map<int, string>::value_type(3, "cccc"));
    mapTest.insert(map<int, string>::value_type(2, "bbbb"));

for (map < int, string, /*greater<int> */MyGreater >::const_iterator it = mapTest.begin(); it != mapTest.end(); ++it)
    {
        cout << it->first << " " << it->second << endl;
    }

return 0;
}

输出为:

3 cccc

2 bbbb

1 aaaa

MyGreater 类并不是以模板实现,只是比较key 值为int 类型的大小。

四、函数对象与算法

在STL一些算法中可以传入函数指针,实现自定义比较逻辑或者计算,同样地这些函数也可以使用函数对象来代替,直接看例程再稍

作分析:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

void PrintFun(int n)
{
    cout << n << ' ';
}

void Add3(int &n)
{
    n += 3;
}

class PrintObj
{
public:
    void operator()(int n)
    {
        cout << n << ' ';
    }
};

class AddObj
{
public:
    AddObj(int number) : number_(number)
    {

}
    void operator()(int &n)
    {
        n += number_;
    }

private:
    int number_;
};

class GreaterObj
{
public:
    GreaterObj(int number) : number_(number)
    {

}
    bool operator()(int n)
    {
        return n > number_;
    }
private:
    int number_;
};

int main(void)
{
    int a[] = {1, 2, 3, 4, 5};
    vector<int> v(a, a + 5);

/*for_each(v.begin(), v.end(), PrintFun);
    cout<<endl;*/

for_each(v.begin(), v.end(), PrintObj());
    cout << endl;

/*for_each(v.begin(), v.end(), Add3);
    for_each(v.begin(), v.end(), PrintFun);
    cout<<endl;*/

for_each(v.begin(), v.end(), AddObj(5));
    for_each(v.begin(), v.end(), PrintFun);
    cout << endl;

cout << count_if(a, a + 5, GreaterObj(3)) << endl; //计算大于3的元素个数

return 0;
}

输出为:

1 2 3 4 5

6 7 8 9 10

2

回顾for_each 的源码,其中有这样一句: _Func(*_ChkFirst); 也就是将遍历得到的元素当作参数传入函数。

上面程序使用了函数对象,实际上可以这样理解 PrintObj()(*_ChkFirst); 即 PrintObj() 是一个匿名的函数对象,传入参

count_if 中的 GreaterObj(3) 就类似了,将遍历的元素当作参数传递给operator(), 即若元素比3大则返回为真。

五、STL内置的函数对象类

参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

转载于:https://www.cnblogs.com/alantu2018/p/8471438.html

函数对象、 函数对象与容器、函数对象与算法相关推荐

  1. 使用脚本自动创建AD中的层次化结构容器及对象

    新年伊始,万象更新.借用在年终总结里的第一句话.2009年了,继续更新BLOG.今年初准备更新2个大主题,1是WINSERVER相关的一些东西,包括2008.应用技巧.部署及各种工具等:2是OCS20 ...

  2. python 函数可以作为容器对象的元素_14、函数对象和闭包

    目录:一 函数对象1.1 函数可以被引用 1.2 函数可以作为容器类型的元素 1.3 函数可以作为参数传入另外一个函数 1.4 函数的返回值可以是一个函数 二 闭包函数2.1 闭与包 2.2 闭包的用 ...

  3. python命名空间和闭包_Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】...

    本文实例讲述了Python函数基础用法.分享给大家供大家参考,具体如下: 一.什么是命名关键字参数? 格式: 在*后面参数都是命名关键字参数. 特点: 1.约束函数的调用者必须按照Kye=value的 ...

  4. Day04:函数参数、对象、嵌套、闭包函数和装饰器

    上节课复习:     1.什么是函数         函数就是具备某一功能的工具     2.为何用函数         1.程序的组织结构和可读性         2.减少代码冗余         ...

  5. python (第八章)补充-可迭代对象(补充高阶函数,以及常用的高阶函数)

    文章目录 可迭代对象 迭代器 什么是迭代器 什么是生成器 生成器的作用 生成器的注意事项 总结: 高阶函数 什么是高阶函数? map()函数 filter()函数 reduce()函数 参考 可迭代对 ...

  6. R语言使用lubridate包的tz函数设置和查询日期、时间对象的时区信息( time zone)

    R语言使用lubridate包的tz函数设置和查询日期.时间对象的时区信息( time zone) 目录

  7. python函数装饰函数_Python精进-装饰器与函数对象

    本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...

  8. 线程同步——内核对象实现线程同步——等待函数

    1 对于内核对象实现线程同步,不得不提三点: 2 1)大多数内核对象既有触发也有未触发两个状态 3 比如:进程.线程.作业.文件流.事件.可等待的计时器.信号量.互斥量 4 2)等待函数:等待函数使线 ...

  9. JNI调用c++函数,该函数的参数是结构体(——对象的传递)

    第三方C++函数接口为 int api_get_logfile(Struct fileinfo tfile),参数是个结构体,且套了另一个结构体: struct fileinfo{  char *fu ...

  10. python装饰器函数-Python精进-装饰器与函数对象

    本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...

最新文章

  1. AttributeError: module ‘matplotlib’ has no attribute ‘artist’
  2. 用最少的机器支撑万亿级访问,微博6年Redis优化历程
  3. 智能指针 shared_ptr 解析
  4. 电力-101/104规约基础1
  5. ztree 后台异步加载_ztree 异步加载示例
  6. 身份证识别技术发展背景及特点
  7. 初识C++——类与对象的详细说明(二)
  8. linux两台电脑共享文件夹怎么设置,快速几步完美实现两台电脑共享上网的设置...
  9. PAT甲级 1087 条条大路通罗马
  10. 工业互联网+化工园区一体化智慧管理解决方案
  11. 公众号文章中怎样图文排版可以实现逐行显示?
  12. Mac上挂载移动硬盘出现Read-only file system问题
  13. java的round函数加点差_【JAVA】Math.Round()函数常见问题“四舍5入”
  14. STM32——时钟系统RCC详细介绍
  15. 什么叫DMZ区?DMZ区有什么作用?应该怎样构建DMZ?
  16. 如何有效练习英语口语
  17. 契约锁解读四川、山东新规,推动采购合同电子化
  18. eclipse卡死未响应的解决办法
  19. SCI论文解读复现【NO.2】基于注意机制的YOLOv5改进算法在行星图像中的应用(代码已复现)
  20. nginx找不到静态(css,js,html)文件404报错,root的解析

热门文章

  1. spring的jar各包作用
  2. 《C++ Primer Plus》第8章 函数探幽 学习笔记
  3. Linux Crontab 定时任务 命令详解
  4. 给DataGrid添加自动增长的序列号
  5. Crystal Reports图表(上)
  6. 请与计算机管理员联系,电脑的限制被取消,请与管理员联系 解决方案
  7. mysql hy000 1005,mysql – ERROR 1005(HY000):无法创建表(errno:150)
  8. centos7配置 console口_centos7基本配置
  9. Python是如何一步步成为热门编程语言的?
  10. linux的上传工具,Linux下精简版上传工具lrzsz