STL六大组件之——仿函数偷窥

时间:2023-02-21 19:38:23

  仿函数(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. &lbrack;转贴&rsqb;从零开始学C&plus;&plus;之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. python 语法常用 lambda

    Python中lambda表达式学习 http://blog.csdn.net/imzoer/article/details/8667176

  2. B-F 字符串匹配算法

    Brute-Froce 算法是串的匹配模式算法中的一种其匹配方式如下: 1.设有字符串 a ,b;a为主串,在 a 中查找 b 串的位置 2.匹配方式如下: 2.1: 分别从 a,b串的第一个元素开始 ...

  3. ECshop设置301最快捷最简单的方法

    ECshop设置301最快捷最简单的方法 在 init.php中加入以下代码 if (strtolower($_SERVER['SERVER_NAME'])!='www.fz1688.com') { ...

  4. MySQL技术内幕汇总

    MySql技术内幕之MySQL入门(1) MySql技术内幕之MySQL入门(1) 检查系统中是否已经安装了MySQL sudo netstat -tap | grep mysql 若没有显示已安装结 ...

  5. C&num; 使用 Lotus notes 公共邮箱发送邮件

    公司的邮件系统用的是反人类的 Lotus notes, 你敢信? 最近要实现一个功能,邮件提醒功能,就是通过自动发送提醒邮件 前前后后这个问题搞了2天,由于公司的诸多条件限制,无法直接调用到公司发送邮 ...

  6. 开启Java之旅

    学习应用系统的服务器开发,也许并不算什么“旅行”,也不会那么‘愉快’.但是,我希望这次能够同以往有所不同,更加努力地学习J2EE. 从2月份开始,从事web前端开发,并在公司的的项目中,独立完成了4个 ...

  7. 浅谈AC自动机

    写在前面:从10月23日开始写这篇博文,离NOIP2018只有十多天了.坚持不停课的倔强蒟蒻(我)尽量每天挤时间多搞一搞信竞(然而还要准备期中考试).NOIP争取考一个好成绩吧. 一.简介 AC自动机 ...

  8. js判断手机系统(Android或IOS),跳转相应下载地址

    <script type="text/javascript"> $(document).ready(function(e) { var u = navigator.us ...

  9. C&plus;&plus; stringstream 简化数据类型转换

    C++标准库中的<sstream>提供了比ANSI C的<stdio.h>更高级的一些功能,即单纯性.类型安全和可扩展性. 在C++中经常会使用到snprintf来格式化一些输 ...

  10. 使用jQuery的分页插件jquery&period;pagination&period;js进行分页

    1,需要用到jquery.pagination.js和pagination.css https://pan.baidu.com/s/1G3PLQSRGjvLxl2ryqpV76w https://pa ...