C++仿函数(functor)详解

  所谓的仿函数(functor),是通过重载()运算符模拟函数形为的类。

  因此,这里需要明确两点:

  1 仿函数不是函数,它是个类;

  2 仿函数重载了()运算符,使得它的对你可以像函数那样子调用(代码的形式好像是在调用

函数)。

  看下面的实例:

#include <iostream>

using namespace std;

const int CMP_LES = -1;

const int CMP_EQU = 0;

const int CMP_BIG = 1;

class Comparer

{

public:

Comparer(int cmpType)

{

m_cmpType = cmpType;

}

bool operator ()(int num1, int num2) const

{

bool res;

switch(m_cmpType)

{

case CMP_LES:

res = num1 < num2;

break;

case CMP_EQU:

res = num1 == num2;

break;

case CMP_BIG:

res = num1 > num2;

break;

default:

res = false;

break;

}

return res;

}

private:

int m_cmpType;

};

void Swap(int &num1, int &num2)

{

int temp = num1;

num1 = num2;

num2 = temp;

}

void SortArray(int array[], int size,const Comparer &cmp)

{

for (int i = 0; i < size - 1; ++i)

{

int indx = i;

for (int j = i + 1; j < size; ++j)

{

if (cmp(array[indx], array[j]))

{

indx = j;

}

}

if (indx != i)

{

Swap(array, array[indx]);

}

}

}

void ListArray(int array[], int size)

{

for (int i = 0; i < size; ++i)

{

cout << array << " ";

}

}

#define ARY_SIZE 10

int main()

{

int array[ARY_SIZE] = {10, 12, 9, 31, 93, 34, 98, 9, 1, 20};

cout << "The initial array is : ";

ListArray(array, ARY_SIZE);

cout << endl;

SortArray(array, ARY_SIZE, Comparer(CMP_BIG));

cout << "The ascending sorted array is :";

ListArray(array, ARY_SIZE);

cout << endl;

SortArray(array, ARY_SIZE, Comparer(CMP_LES));

cout << "The descending sorted array is : ";

ListArray(array, ARY_SIZE);

cout << endl;

return 0;

}

运行结果:

The initial array is : 10 12 9 31 93 34 98 9 1 20

The ascending sorted array is :1 9 9 10 12 20 31 34 93 98

The descending sorted array is : 98 93 34 31 20 12 10 9 9 1

  程序中定义了一个仿函数Comparer,它重重载了()运算符:

  Comparer::bool operator ()(int num1, int num2) const;

  这里温习一下运算符重载的方式:

  ret_type operator opt(array_list);

  其中,ret_type为运算符重载后返回值的类型,operator为c++运算符重载专用关健字,opt为所要重载的运算符,如+, -, *, /, [], ()...

  于是我们可以解读Comparer::bool operator ()(int num1, int num2) const的意义:

  bool限定了()的返回值为布尔类型,(int num1, int num2)指定了运算符()的参数形式,const使得应该运算符可被它的const对象调用。()运算符中根据m_cmpType值返回不同方式下两整数的比较值。

  函数void SortArray(int array[], int size, const Comparer &cmp)用于给数组排序。其中,array[]指定所要排序的数组对象,size限定数组元素个数,cmp为Comparer对象的引用,用作对元素的比较使用,前面使用const修饰是向函数调用都声明,在函数内不会有修改该对象任何数据的形为。注意SortArray中的代码:

if (cmp(array[indx], array[j]))

{

indx = j;

}

  其中,cmp为Comparer类的一个对象,但这里的用法好像它是某个函数的样子。这就是仿函数的真谛。

  别外,void Swap(int &num1, int &num2)完成交换num1与num2值的功能。int &num1表示函数参数使用的引用,用久了c的朋友也许更习惯了void Swap(int *num1, int *num2),但在c++中这个习惯要改了,引用和指针一样高效,但引用要比指针更直观。下面是指针版的Swap函数:

void Swap(int *num1, int *num2)

{

int temp = *num1;

*num1 = *num2;

*num2 = temp;

}

  实现的功能与程序中使用的一模一样,替换掉程序照样正常工作。仔细比较引用版与指针版的Swap()函数,我相信大多数人会爱上C++的引用版。

C++仿函数(functor)详解的更多相关文章

  1. [GeekBand] STL 仿函数入门详解

    本文参考文献::GeekBand课堂内容,授课老师:张文杰 :C++ Primer 11 中文版(第五版) page 37 :网络资料: 叶卡同学的部落格  http://www.leavesite. ...

  2. C++ 谓词(predicate) 与 仿函数 ( functor (function object))

    谓词与函数对象 谓词 predicate C++ 标准定义谓词如下: The Predicate parameter is used whenever an algorithm expects a f ...

  3. for_each的各种情况下的使用详解

    原创作者:http://oomusou.cnblogs.com 配合<C++ Template>(简体中文)使用 http://download.csdn.net/detail/qq239 ...

  4. STL之heap与优先级队列Priority Queue详解

    一.heap heap并不属于STL容器组件,它分为 max heap 和min heap,在缺省情况下,max-heap是优先队列(priority queue)的底层实现机制.而这个实现机制中的m ...

  5. C++中的STL中map用法详解(转)

    原文地址: https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html C++中的STL中map用法详解   Map是STL的一个关联容器,它提供 ...

  6. Java反序列化漏洞详解

      Java反序列化漏洞从爆出到现在快2个月了,已有白帽子实现了jenkins,weblogic,jboss等的代码执行利用工具.本文对于Java反序列化的漏洞简述后,并对于Java反序列化的Poc进 ...

  7. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  8. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  9. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

随机推荐

  1. JAVA面试题集之基础知识

                           JAVA面试题集之基础知识 基础知识:  1.C 或Java中的异常处理机制的简单原理和应用. 当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就 ...

  2. MySQL 主键冲突,无法插入数据

    数据库版本:5.6.16 问题:开发来电话说仓库无法下单,程序插入数据提示:入库单 xxxx1589762285确认失败:Duplicate entry '8388607' for key 'PRIM ...

  3. 【转载】mysql 四种隔离级别分析

    sql标准中,有四种隔离级别,各个离级别都有各自的规则,隔离级别越低,允许并发越大,消耗的资源越少,但是越不安全,下面就mysql数据库来分别介绍一下(每个存储引擎实施的隔离级别会有稍微的不同)mys ...

  4. Intel格式和AT&T格式汇编区别

    一.AT&T 格式Linux 汇编语法格式 在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀:而在 Intel 汇编格式中,寄存器名不需要加前缀.例如: AT&T 格 ...

  5. VirtualBox内Linux系统与Windows共享文件夹

    在日常工作或学习中我们经常需要在一台电脑上同时使用Windows和Linux(这里以Ubuntu为例)两个系统,我们通常的做法有两种: 一种安装双系统(双系统的安装方法经验里已经有很多,大家可以去参照 ...

  6. SOS.dll(SOS 调试扩展)

      SecAnnotate.exe(.NET 安全批注器工具) SignTool.exe(签名工具) Sn.exe(强名称工具) SOS.dll(SOS 调试扩展)   SqlMetal.exe(代码 ...

  7. 敏捷开发之道(四)Scrum概述

    上次的博文敏捷开发之道(二)极限编程XP和敏捷开发之道(三)极限编程XP续中,我们介绍了一下敏捷开发中的XP开发方法,今天咱们来了解另一个比较流行的敏捷开发方法--Scrum. 1.Scrum简介 S ...

  8. Ubuntu实用快捷键

    ALT + TAB: 切换程序窗口Win+w: 显示所有的工作空间,可轻松进行切换 ===== Terminal终端 ===== CTRL + ALT + T: 打开终端 TAB: 自动补全命令或文件 ...

  9. 1231: [Usaco2008 Nov]mixup2 混乱的奶牛 - BZOJ

    Description 混乱的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S ...

  10. HTTP长轮询和短轮询

    http 协议介绍: http 协议是请求/响应范式的, 每一个 http 响应都是由一个对应的 http 请求产生的; http 协议是无状态的, 多个 http 请求之间是没有关系的. http ...