1. 程式人生 > >使用tr1的bind函式模板

使用tr1的bind函式模板

最近把公司的VS2008統一升級為SP1了,雖然還是有些跟不上時代,畢竟C++17標準都出了,但是,對於成熟的商業軟體開發而言,追求更新的C++標準肯定不是正道。升級SP1的VS2008可以支援TR1的C++標準了,算是跟上了部分C++11的腳步。本文將說說TR1中新functional標頭檔案中function和bind模板的使用.

就我個人理解的這個新標準來看,藉由這兩個模板,我們將能更靈活的使用函式指標,比如函式指標的呼叫和使用回撥機制等。通過使用佔位符,我們將可以使用成員函式來進行回撥,不得不說,這讓我們的程式設計方式得以更加現代化。

如程式碼所示:

#include <functional>

typedef std::tr1::function<void (int)>  Functor;

如上,通過std::tr1::function 我們定義了Functor的函式型別,該類函式的返回值為void ,引數為int型別,

void showNum(int param)
{
std::cout << "param is : "<<param <<std::endl;
}

void testSimpleFunctional()
{
Functor namedFunc = Functor(&showNum);
Functor namedFunc2 = bind(&showNum,std::tr1::placeholders::_1);

namedFunc(22);
namedFunc2(33);
}

返回的結果如你所料:

param is : 22
param is : 33

首先,我們定義了一個void int型別的函式showNum,然後將函式以模板HandlerEvent賦值給namedFunc,然後呼叫namedFunc,而namedFunc2 則使用bind模板,將showNum繫結到namedFunc2上,使用佔位符std::tr1::placeholders::_1

來表明其引數,其最後的效果 和直接呼叫showNum都是一樣的。那麼,你可能會問,我還不如直接呼叫showNum來的爽快,是的,在這種情況下,確實如此。

那麼,使用std::tr1::function的場景在哪裡呢,答案之一是事件回撥,答案之二是委託;

事件回撥

回撥算是老生常談了,在非同步非阻塞的事件驅動的程式設計模型中,回撥機制屬於一等公民,像Nodejs這樣的平臺,回撥已經內嵌為基本實現了,這裡不展開說明了。為了實現回撥,以前,我們經常使用的就是函式指標。現在,讓我們使用bind來實現下:

Show Me The Code

class CallBackCls
{
public:
void setCallback(const Functor& callBackFunc){
m_callBackFunc = callBackFunc;
}

private:
Functor m_callBackFunc;
public:
void run(int param){
//below to do the opetration
std::cout << "callcls handle it done and call" << std::endl;
//operation done and notify the callee
if(m_callBackFunc){
m_callBackFunc(param);
}
}
};

class MainCls
{
public:
MainCls(int x):m_x(x){
m_callBackCls.setCallback(std::tr1::bind(&MainCls::onCallBack,this,x));
}
void mainRun(){
m_callBackCls.run(m_x);
}
private:
void onCallBack(int param){
std::cout << "after callback parm callBackFunc in Main is:"<<param <<std::endl;
}
CallBackCls m_callBackCls;
int m_x;
};

//在Main函式中測試
MainCls cd = MainCls(555);
cd.mainRun();

結果:

callcls handle it done and call:
parm callBackFunc in Main is:555

分析可知:通過bind將MainCls的成員函式onCallBack以及其引數繫結為回撥函式,執行run後,CallBackCls的run函式將在執行完自己的任務後回撥MainCls的成員函式onCallBack,通過這種方式,可以很好的達到非阻塞的目的。

另外,通過類的繼承,虛擬函式等,我們可以向深挖掘更多高階的用法,這裡不展開了。

委託

委託(delegate)在C#裡風生水起,而在C++裡卻是相對沉寂,因為C++沒有,只有類似的委託。可參考長文

面向物件的函式指標也被稱為閉包(closures) 或委託(delegates), 在類似的語言中已經體現出了它的價值. 在 Delphi(Object Pascal) 中, 他們是 VCL (Borland's Visual Component Library, 寶藍視覺化元件) 的基礎. 最近的 C# 讓委託的概念更為流行, 這也成為 C# 成功的因素之一. 在許多程式中, 委託可以簡化由鬆耦合物件組成的高階設計模式(觀察者模式, 策略模式, 狀態模式)的使用. 毫無疑問, 委託在 C++ 中也是非常有用的.

理論上說,委託應該算是回撥的一種,即 委託機制的本質就是呼叫成員函式的函式指標,實現回撥。事實上,本文開篇的例子已經算是委託的一種了,但是沒有涉及到具體的類,顯示有些多餘,而一旦使用了類的成員函式,我們就將物件的狀態以及類的成員變數都彙集在一起,函式指標的可用性被大大增強了。例子有機會再補充吧。