1. 程式人生 > >boost::bind繫結成員函式時,第一個引數傳遞物件的特殊情況

boost::bind繫結成員函式時,第一個引數傳遞物件的特殊情況

boost::bind(&memberfunction, obj, _1, _2........)類似這樣的用法,我們叫做成員函式繫結,boost庫的文件中說的很清楚,第一個引數可以是value、pointer和reference,即傳值、傳地址和傳引用都是可以的,所以在一般情況下,下面三種使用bind的形式都是成立的。

class A
{
public:
    
void func();
}
;


A a;
A
& r = a;

boost::bind(
&A::func, a);
boost::bind(
&a::func, &a);
boost::bind(
&a::func, r);
由上面的程式碼可以看出,我們可以隨便傳任意一種類物件的形式,函式模板會自動尋找最為匹配的為我們實現。但是有兩種情況是特殊的,即:
1、該物件不可進行拷貝建構函式。
2、該物件不可隨意被析構。
發現這個問題是在我編寫單件模式時的遇見的,當時發現我的單件物件在bind中被析構了一次,這很不尋常,為什麼bind會呼叫第一個引數的析構呢?跟蹤進了boost的原始碼才發現,原來所有的引數都會被拷貝一遍,然後析構一遍,這樣一來,我們傳遞引數的時候就會有一些小麻煩了,首先必須保證引數能夠被拷貝而不影響邏輯和資料一致性,其次,引數能夠被析構而不影響邏輯和資料一致性。單件是全域性性質的資料,所以絕對不可以析構,那麼這種情況的話,我們只好傳遞單件物件的地址,而不能傳遞值或引用。

另:附上出錯問題的程式碼如下
class InputDevice
    : 
public EventSource
    , 
public Singleton<InputDevice>
{
public:
    
}
;

class TestUI
    : 
public Singleton<TestUI>
{
public:
    
~TestUI(){
        std::cout
<<"~TestUI"<<std::endl;
    }

    
void processKeyboard(EventArgs& args){
        std::cout
<<"鍵盤響應"
<<std::endl;
    }


    
void processMouse(EventArgs& args){
        std::cout
<<"滑鼠響應"<<std::endl;
    }

}
;


int _tmain(int argc, _TCHAR* argv[])
{
    
new FrameUpdaterManager;
    
new DelayEventSender;
    
new InputDevice;
    
new TestUI;

    InputDevice::getSingleton().mEventSet.addEvent(
"KeyDown
", Event());
    InputDevice::getSingleton().mEventSet.addEvent(
"KeyUp", Event());
    InputDevice::getSingleton().mEventSet.addEvent(
"MouseLDown", Event());
    InputDevice::getSingleton().mEventSet.addEvent(
"MouseLUp", Event());
    InputDevice::getSingleton().mEventSet.addEvent(
"MouseRDown", Event());
    InputDevice::getSingleton().mEventSet.addEvent(
"MouseRUp", Event());


    
//TestUI& ui = TestUI::getSingleton(); // 用此行便會出錯
    TestUI* ui = TestUI::getSingletonPtr();

    
// 出錯開始
    InputDevice::getSingleton().mEventSet["KeyDown"+= boost::bind(&TestUI::processKeyboard, ui, _1);
    InputDevice::getSingleton().mEventSet[
"KeyUp"+= boost::bind(&TestUI::processKeyboard, ui, _1);

    InputDevice::getSingleton().mEventSet[
"MouseLDown"+= boost::bind(&TestUI::processMouse, ui, _1);
    InputDevice::getSingleton().mEventSet[
"MouseLUp"+= boost::bind(&TestUI::processMouse, ui, _1);
    InputDevice::getSingleton().mEventSet[
"MouseRDown"+= boost::bind(&TestUI::processMouse, ui, _1);
    InputDevice::getSingleton().mEventSet[
"MouseRUp"+= boost::bind(&TestUI::processMouse, ui, _1);


    delete TestUI::getSingletonPtr();
    delete InputDevice::getSingletonPtr();
    delete DelayEventSender::getSingletonPtr();
    delete FrameUpdaterManager::getSingletonPtr();
    
return0;
}