2012-08-28 106 views
0

考慮片段:多個回調處理

# include <iostream> 

# include <boost/scoped_ptr.hpp> 
# include <boost/shared_ptr.hpp> 

# include <boost/function.hpp> 
# include <boost/array.hpp> 
# include <boost/asio.hpp> 
# include <boost/thread.hpp> 
# include <boost/thread/locks.hpp> 
# include <boost/bind.hpp> 
# include <boost/noncopyable.hpp> 

# include <boost/variant.hpp> 


class DataLink {}; 
class Metadata {}; 
class Image {}; 

typedef boost::function<void(DataLink const&, Metadata const& , Image const&)> Handler ; 
typedef boost::function<void(Metadata const& , Image const&)> Handler2 ; 
typedef boost::function<void(Image const&)> Handler3 ; 

typedef boost::variant<DataLink, Metadata, Image> Variant; 



enum callbackHandler { link_enum, meta_enum, image_enum }; 
class Worker { 
    Handler callBack ; 
    //Handler2 callBack2 ; 
    //Handler3 callBack3 ; 

    DataLink dlink; 
    Metadata meta ; 
    Image img ; 

    callbackHandler handlerEnum ; 

public : 
    Worker (const Handler& handler) 
    : callBack (handler) 
    {} 
    //Worker (const Handler2& handler) 
    //: callBack2 (handler) 
    // {} 
    //Worker (const Handler3& handler) 
    //: callBack3 (handler) 
    // {} 

    void Image () { 
    // update the img object 
    // invoke call back 
    handlerEnum = image_enum ; 
    //const std::type_info& xxx = callBack.target_type(); 
    //std::cout << xxx.raw_name() << std::endl; 
    callBack (dlink, meta, img) ; 
    } 

    void Metadata () { 
    // update the meta object 
    // invoke call back 
    handlerEnum = meta_enum ; 
    callBack (dlink, meta, img) ; 
    } 

    void Dlink () { 
    // update the link object 
    // invoke call back 
    handlerEnum = link_enum ; 
    callBack (dlink, meta, img) ; 
    } 

    callbackHandler getHandlerType() { return handlerEnum ; } 
}; 

class Foo { 
    Worker *ptrWorker ; 
public : 
    Foo() 
    : ptrWorker(0) 
    {} 

    void callback (DataLink const& d, Metadata const& m , Image const& i) { 
    callbackHandler tt = ptrWorker->getHandlerType(); 
    if (tt == image_enum) { 
     std::cout << "Image object " << std::endl; 
    } 
    if (tt == meta_enum) { 
     std::cout << "Meta object " << std::endl; 
    } 
    if (tt == link_enum) { 
     std::cout << "Link object " << std::endl; 
    } 

    } 
    bool start() { 
    ptrWorker = new (std::nothrow) Worker (boost::bind (&Foo::callback, this, _1, _2, _3)); 
    if (!ptrWorker) { 
     return - 1 ; 
    } 
    } 
    void testWorker() { 
    ptrWorker->Image() ; 
    ptrWorker->Metadata() ; 
    ptrWorker->Dlink() ; 
    } 
}; 

int main() { 
    Foo f; 
    f.start() ; 
    f.testWorker() ; 
    std::cin.get() ; 
} 

註釋掉構造允許我補充了Handler2和Handler3支持,但是有沒有一種方法來確定傳遞給Worker類的構造函數的處理程序?目前成員函數Metadata,Image和Dlink使用'callBack'對象。如果用戶處理程序在另一個處理程序中傳遞,則需要做出區分 - 例如Handler2

事實上,我需要使用枚舉來實現,實際上我自己的類型系統(在一個區別聯合 - 又名,一個變種),也是一個肯定的跡象,設計需要一些重新思考,所以在這種情況下,我打開重新設計。必須有N-1個僞處理程序(即任何時候只有一個處理程序正在使用,而其他處理程序只是在那裏無所事事)在該類中定義尖叫混淆和低粘性對象模型,但誰知道。

+0

這是什麼,它的目的*做*? –

回答

0

你可以這樣使用仿函數,從虛基類派生實現:

struct CallbackBase 
{ 
    // Dummy virtual functions that does nothing 
    virtual operator()(DataLink const &, Metadata const &, Image const &) {} 
    virtual operator()(Metadata const &, Image const &) {} 
    virtual operator()(Image const &) {} 
}; 

class Worker 
{ 
    CallbackBase &callback_; 

public: 
    Worker(const CallbackBase &callback) 
     : callback_(callback) 
     { } 

    void Image() 
     { 
      // Do something... 

      callback_(img); 
     } 

    void Metadata() 
     { 
      // Do something... 

      callback_(meta, img); 
     } 

    void Dlink() 
     { 
      // Do something... 

      callback_(dlink, meta, img); 
     } 
}; 

struct MyCallback : public CallbackBase 
{ 
    virtual operator()(Image const &) 
     { 
      // Do something useful here 
     } 
}; 

MyCallback my_callback; 
Worker my_worker(my_callback); 

因爲在基回調類的重載時,Worker類可以調用任何人在正確的位置,而你只實現你在派生回調類中實際需要的回調。