仿函数(functor),就是使一个类或类模板的使用看上去象一个函数。其实现就是类或类模板中对operator()进行重载,这个类或类模板就有了类似函数的行为。仿函数是智能型函数就好比智能指针的行为像指针,其就可看作是一个指针。但是智能指针是定义的一个类对象,所以在具备指针功能的同时也有其他的能力。仿函数的能力也可以超越operator()。因为仿函数可以拥有成员函数和成员变量,这意味着仿函数拥有状态。另一个好处是可以在执行期初始化它们。

预定义的仿函数

算术类

加法:plus<T>;减法:minus<T>;乘法:multiplies<T>;除法:divides<T>;求余:modulus<T>;否定:negate<T>

关系运算类

等于:equal_to<T>;不等于:not_equal_to<T>;大于:greater<T>;大于等于:greater_equal<T>;小于:less<T>;小于等于:less_equal<T>

逻辑运算类

除了否定为一元,其他都为二元仿函数。与:logical_and<T>;或:logical_or<T>;否:logical_not<T>

  下面是一个哈夫曼编码示例,遇到了需要对一个文件中的所有字符进行权重计算以创建每个字符的最终编码的过程,这其中有一个步骤是需要遍历已有的字符权重表以查找当前从文件中取得的字符是否已经存在于该表中,如果存在就将该表中的该字符权重加一,如不存在则需要新建一个存储 node 以存储该字符,并将该 node 结构添加到已有的权重表中。考虑到需要在权重表中进行字符查找以及之后创建 Huffman Tree 时可能需要对该表各项进行排序所以选用 vector<Node>作为存储容器,查找及排序可以使用 algorithm 头文件当中的 sort 和 find 算法。

 #include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>//for bind2nd func; #ifndef HUFFMAN_H
#define HUFFMAN_H using namespace std; class Huffman
{
public:
Huffman(void);
//huffman(File file, File srcTable);
void encode(const string& file);
void decode(const string& file, const string& srcTable) const;
~Huffman();
private:
//table node
typedef struct
{
char letter;
int level;
int parent;
int direction;//-1 for no parent, 0 for left, 1 right;
}Node;
vector<Node> nodeTable;//can be sorted; //仿函数,用于find_if,侦测字符是否已经存在;
//template <typename T1, typename T2>
class Comparer : public binary_function<Node, char, bool>
{
public:
Comparer(const char ch):_ch(ch){}; const bool operator()(const vector<Node>::value_type& node, char ch) const
{
return node.letter == ch;
} private:
char _ch;
};
}; #endif
 #include "Huffman.h"

 Huffman::Huffman(void)
{
//dummany;
} void Huffman::encode(const string& file)
{
ifstream fin;
fin.open(file.c_str());
char ch;
while(fin.get(ch))
{
if (nodeTable.size() != )
{
//仿函数
vector<Node>::iterator result = find_if(nodeTable.begin(),nodeTable.end(),bind2nd(Comparer(ch), ch)); if (result == nodeTable.end())
{
Node* node = new Node;
node->letter = ch;
node->level = ;
node->parent = ;
node->direction = -;
}
else
{
result->level += ;
}
}
else
{
Node* node = new Node;
node->letter = ch;
node->level = ;
node->parent = ;
node->direction = -;
}
}
fin.close(); //huffman tree; } void Huffman::decode(const string& file, const string& srcTable) const
{
//dummany;
} Huffman::~Huffman(void)
{
//dummany;
}

  此处仿函数调用过程是这样的:find_if(nodeTable.begin(), nodeTable.end(), Comparer(ch))中 Comparer(ch)只是创建了 Comparer 类的匿名方法,重载的 operator() 真正的调用是在接下来将要看到的 find_if 模板函数的这一句 pred(*first);代码中不使用 find 而使用 find_if 是因为需要进行查找的不是 prime type 而是自行编写的符合类型,find_if 的函数原型参考如下,从原型中可以看到第一个参数是以默认的方式进行的:

 template<class InputIterator, class Predicate>
InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred )
{
for ( ; first!=last ; first++ ) if ( pred(*first) ) break;
return first;
}

  bind2nd 函数的作用是将 二元算子(binary functor, bf) 转化为一元算子(unary functor, uf) 还有一个类似的 bind1st ,使用时需要包含 functional 头文件;进行比较的仿函数需要继承 binary_functor<typename T1,typename T2,typename T3>,T3 一般为 bool 值, binary_functor 原型如下:

 template<class Arg1,class Arg2,class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};

  这里使用的是 bind2nd 直接将得到的 char 参数 bind 到 Comparer 仿函数中,当然可以使用直接传参数到 Comparer 仿函数中人的方法,从 Huffman.h 和 Huffman.cpp 的注释中可以看到存在不同的可行方法。

STL六大组件之——仿函数偷窥的更多相关文章

  1. STL —— STL六大组件

    注:以下内容摘自 http://blog.csdn.net/byxdaz/article/details/4633826 STL六大组件 容器(Container) 算法(Algorithm) 迭代器 ...

  2. STL 六大组件 功能与运用

    STL 提供六大组件,彼此可以组合套用: 1 容器(containers):各种数据结构,如vector,list,deque,set,map,用来存放数据,从实现的角度来看,STL容器是一种clas ...

  3. [转贴]从零开始学C++之STL(一):STL六大组件简介

    一.STL简介 (一).泛型程序设计 泛型编程(generic programming) 将程序写得尽可能通用 将算法从数据结构中抽象出来,成为通用的 C++的模板为泛型程序设计奠定了关键的基础 (二 ...

  4. STL六大组件简介

    一.STL简介 (一).泛型程序设计 泛型编程(generic programming) 将程序写得尽可能通用 将算法从数据结构中抽象出来,成为通用的 C++的模板为泛型程序设计奠定了关键的基础 (二 ...

  5. STL六大组件之——适配器代表大会

    适配器也是一种常用的设计模式: 将一个类的接口转换为另一个类的接口,使得原本因接口不兼容而不能合作的两个类可以一起运作.STL提供三种适配器:改变容器接口的容器适配器.改变迭代器接口的迭代器适配器以及 ...

  6. STL六大组件之——分配器(内存分配,好深奥的东西)

    SGI设计了双层级配置器,第一级配置器直接使用malloc()和free(),第二级配置器则视情况采用不同的策略:当配置区块超过128bytes时,视之为“足够大”,便调用第一级配置器:当配置区小于1 ...

  7. STL六大组件之——迭代器这个东西

    迭代器:除了在其它语言中司空见惯的下标法访问容器元素之外,C++语言提供了一种全新的方法——迭代器(iterator)来访问容器的元素.迭代器其实类似于引用,指向容器中某一元素.换个方式来说,容器就是 ...

  8. STL六大组件之——算法小小小小的解析

    参考自侯捷的<stl源码剖析> stl算法主要分为非可变序列算法(指不直接修改其所操作的容器内容的算法),可变序列算法(指可以修改它们所操作的容器内容的算法),排序算法(包括对序列进行排序 ...

  9. STL六大组件之——容器知识大扫盲

    STL中的容器主要涉及顺序容器类型:vector.list.deque,顺序容器适配器类型:stack.queue.priority_queue.标准库中的容器分为顺序容器和关联容器.顺序容器(seq ...

随机推荐

  1. 使用CXF与Spring集成实现RESTFul WebService

    以下引用与网络中!!!     一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存 ...

  2. RN学习1——前奏,app插件化和热更新的探索

    react_native_banner-min.png React Native(以下简称RN)有大量前端开发者的追捧.前端开发是一个活跃的社区,一直尝试着一统前后端,做一个全栈开发,RN就是他们在客 ...

  3. windows下安装ubantu

        首先声明我是一个linux大菜鸟,之所以学这个,一个是好玩,另外做DL的一些软件如Caffe要在这个平台上运行,所以没事就鼓捣鼓捣.linux是一种内核,市场上支持这种内核的操作系统有uban ...

  4. 【mysql的编程专题⑤】自定义函数

    用户自定义函数(user-defined function,UDF) 是一种对mysql的扩展途径,其用法与内置函数相同 创建自定义函数 语法 create function function_nam ...

  5. 解决不安装VC运行库(VC2005,VC2008),程序运行出错的方法

    因为VS2005以后程序采用了manifest的生成方式,所以发布的时候要和运行库一起发布.但是我们平时开发和发布的时候如果都要客户安装运行库,那就不太方便了.你可以Microsoft下载:http: ...

  6. Python基本程序结构

    条件判断: 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断.比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现:

  7. java对称加密(AES)

    java对称加密(AES) 博客分类: Java javaAES对称加密  /** * AESHelper.java * cn.com.songjy.test * * Function: TODO * ...

  8. idea 找不到 没有 tomcat server

    follow me 1. 2. 3. 4.

  9. SQL Server 和Oracle 数据类型对应

    SqlServer 2k转换为Oracle 10g 列名 SqlServer数据类型 SqlServer长度 Oracle数据类型 column1 bigint 8 NUMBER(19) column ...

  10. 5 commands to check memory usage on Linux

    Memory Usage On linux, there are commands for almost everything, because the gui might not be always ...