最近在看陳碩的MUDUO網絡通信庫的過程中,發現作者大量使用了Boost::function以及Boost::bind功能,為了能夠正常的學習作者的代碼,決定先弄明白function以及bind的功能。
Boost::Function 是對函數指針的對象化封裝,在概念上與廣義上的回調函數類似。相對于函數指針,function除了使用自由函數,還可以使用函數對象,甚至是類的成員函數,這個就很強大了哈。
1. 一個簡單的示例代碼
#include
#include
#include
using namespace std;
class TestA
{
public:
void method()
{
cout<
}
void method(int a, int b)
{
cout<
<
<
}
};
void sum(int a, int b)
{
int sum = a + b;
cout<
}
int main()
{
boost::function f;
TestA test;
f = boost::bind(&TestA::method, &test);
f();
f = boost::bind(&TestA::method, &test, 1, 2);
f();
f = boost::bind(&sum, 1, 2);
f();
}
輸出結果:
[email protected] ~/source
$ ./BoostFunction.exe
TestA: method: no arguments
TestA: method: with argumentsvalue of a is:1value of b is 2
sum: 3
2. 應用:Thread封裝
在實作自定義的線程類時,曾經這麼幹過:定義虛函數run(),使用者自定義的CustomThread::Thread後,自己實作run()函數就OK了。 當時覺得這麼做也不錯。
現在有了boost::function/boost::bind我們可以這麼幹:
定義一個線程類:
.h檔案
#include
#include
#include
#include
using namespace std;
class Thread
{
typedef boost::function ThreadFun;
public:
Thread(const ThreadFun& threadFun,const string& threadName = string());
pid_t getThreadId();
string getThreadName();
int start();
private:
static void* startThread(void* thread);
private:
pthread_tm_thread; //線程句柄
pid_tm_tid; //線程ID
stringm_strThreadName; //線程名稱
boolm_bStarted; //線程是否啟動
ThreadFunm_func; //線程處理函數
};
.cpp檔案
#include "thread.h"
Thread::Thread(const Thread::ThreadFun& threadFun, const string& threadName):
m_func(threadFun), m_strThreadName(threadName)
{
}
int Thread::start()
{
m_tid = pthread_create(&m_thread, NULL, &startThread, this);
return 0;
}
void* Thread::startThread(void* obj)
{
Thread* thread = static_cast(obj);
thread->m_func();
return NULL;
}
pid_t Thread::getThreadId()
{
return m_tid;
};
stringThread::getThreadName()
{
return m_strThreadName;
}
測試程式
void ThreadProcess()
{
int count = 100;
for (int i = 0; i < count; i++)
{
if (i % 10 == 0)
cout<
cout<
}
}
int main()
{
boost::function f;
f = boost::bind(&ThreadProcess);
Thread thread(f, "ThreadTest");
thread.start();
sleep(1000*1000);
return 0;
}
輸出結果(Cygwin):

>根據上述程式,我們可以發現,這樣我們就不需要定義很多很多的類去繼承Thread類,而隻需要寫好線程運作函數,set到Thread類中即可。不過也不能說利用虛函數留接口給使用者實作就不好,隻不過現在多了一種方法。(陳碩很反對用虛函數作為結構提供給使用者去做實作,但是我現在還沒有切身的體會覺得那裡不好)
3. 總結
注:
1. 這邊隻是簡單的用boost::function/bind結合pthread簡單的實作了一個自己封裝的線程類,
2. boost::function/bind還有很多其他進階用法,我這邊隻是用來當做一個函數指針用了哈
3. 測試環境:cygwin