首先介紹一個簡單的例子
問題描述:
struct stRecordItem
{
char szname[_MAX_NAME_LEN_]; //物品名稱
int dwBaseID; //基本ID
int btItemLvl; //品階
int ncount; //數量
__int64 i64Time; //記錄這條信息的時間,如果有疊加的,按後一個的時間
};
list<stRecordItem> ListRecordItem;
現在要按照 ncount 降序,在 ncount 相同的時候,按btItemLvl的降序排列。
解決方法:www.2cto.com
struct cmp
{
bool operator()(const stRecordItem &st1,const stRecordItem &st2 )
{
if(st1.ncount<st2.ncount)
{
return false;
}
else if(st1.ncount == st2.ncount)
{
if(st1.btItemLvl < st2.btItemLvl)
{
return false;
}
else
return true;
}
else
return true;
}
};
ListRecordItem.sort(cmp());
不言而喻,排序算法的簡潔性與可擴展性都非常好。這個方法就是使用了stl常用的一種方法:仿函數
仿函數的概念:
仿函數(functor),就是使一個類的使用看上去象一個函數。其實現就是類中實現一個operator(),這個類就有了類似函數的行為,就是一個仿函數類了。
http://www.cnblogs.com/rereadyou/articles/2011048.html 有一個比較好的例子,實現了Huffman 編碼與解碼的程序,摘錄如下:
使用 C++ 在 Editplus 中編寫一個 Huffman 編碼與解碼的程序,遇到了需要對一個文件中的所有字符進行權重計算以創建每個字符的最終編碼的過程,這其中有一個步驟是需要遍歷已有的字符權重表以查找當前從文件中取得的字符是否已經存在於該表中,如果存在就將該表中的該字符權重加一,如不存在則需要新建一個存儲 node 以存儲該字符,並將該 node 結構添加到已有的權重表中。
考慮到需要在權重表中進行字符查找以及之後創建 Huffman Tree 時可能需要對該表各項進行排序所以選用 vector<Node>作為存儲容器,查找及排序可以使用 algorithm 頭文件當中的 sort 和 find 算法。
huffman.h
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
//for find_if func;
#include <functional>
//for bind2nd func;
using namespace std;
class Huffman {
public:
Huffman(void);
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;
};
};
Huffman.cpp
#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() != 0)
{
//vector<Node>::iterator result = find_if(nodeTable.begin(),nodeTable.end(),Compare(ch));
//仿函數
vector<Node>::iterator result = find_if(nodeTable.begin(),nodeTable.end(),bind2nd(Comparer(ch), ch));
//lambda 函數方式;
//vector<Node>::iterator result = find_if(nodeTable.begin(),nodeTable.end(),[](const Node& node)->bool{return node.letter == ch;});
if (result == nodeTable.end())
{
Node* node = new Node;
node->letter = ch;
node->level = 1;
node->parent = 0;
node->direction = -1;
}
else
{
result->level += 1;
}
}
else
{
Node* node = new Node;
node->letter = ch;
node->level = 1;
node->parent = 0;
node->direction = -1;
}
}
fin.close();
//huffman tree;
}
void Huffman::decode(const string& file, const string& srcTable) const
{
//dummany;
}
Huffman::~Huffman(void)
{
//dummany;
}
說明:
1、仿函數不是函數,而是一個類,這個類重載了()操作符;
2、仿函數調用過程是這樣的:find_if(nodeTable.begin(), nodeTable.end(), Comparer(ch))
中 Comparer(ch)只是創建了 Comparer 類的匿名方法,重載的 operator() 真正的調用是在
接下來將要看到的 find_if 模板函數的這一句 pred(*first);
3、代碼中不使用 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;
}
4、bind2nd 函數的作用是將 二元算子(binary functor, bf) 轉化為一元算子(unary functor,uf)還有一個類似的bind1st,
使用時需要包含functional頭文件;
5、進行比較的仿函數需要繼承 binary_functor<typename T1,typename T2,typename T3 >,原型如下:
template<class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
還有一些比較有用的博客,可以借鑒參考:
http://www.cnblogs.com/wzh206/archive/2010/03/26/1696983.html //介紹了一些STL的仿函數的應用
http://cunsh.ycool.com/post.1380153.html //實現了一個泛化的仿函數
http://www.soft-bin.com/html/2010/07/21/stl-cpp-functor-tutorial2.html //詳細介紹了STL源碼中對仿函數的使用並解析了remove_if、bind2nd的源代碼(個人覺得非常具有參考性,推薦閱讀)
http://blog.sina.com.cn/s/blog_491c65000100d62y.html //實現了一個泛化的仿函數(>、<、== 、!=)的比較。
摘自 lbqBraveheart的專欄