2009-11-09 84 views
0

我有管理的Win32 C++的RAII類處理使用boost :: shared_ptr的<>,看起來有點像這樣:增加功能的手柄包裝

namespace detail { 
struct NoDelete { void operator()(void*) {}; }; 
}; // namespace detail 

template< typename HANDLE_TYPE, typename HANDLE_DELETER > 
class CHandleT 
{ 
public : 
    explicit CHandleT(HANDLE_TYPE handle, bool delete_on_release = true) 
    { 
     if(delete_on_release) 
      handle_ = Handle(handle, HANDLE_DELETER()); 
     else 
      handle_ = Handle(handle, detail::NoDelete()); 

    }; 

    operator HANDLE_TYPE() const { return static_cast<HANDLE_TYPE>(handle_.get()); }; 

protected: 
    typedef boost::shared_ptr<void> Handle; 
    Handle handle_; 

}; // class CHandleT 

struct DeallocateHandle 
{ 
    void operator()(void* handle) { ::CloseHandle(handle); }; 
}; 

typedef CHandleT< HANDLE, DeallocateHandle > CHandle; 

我想擴展它這樣,而不是寫:

CHandle my_handle(::CreateEvent(NULL, FALSE, FALSE, NULL)); 
::SetEvent(my_handle.get()); 

我可以這樣寫:

CEvent my_event(NULL, FALSE, FALSE, NULL); 
my_event.SetEvent(); 

生活的最好辦法做到這一點爲t o使用CHandle類作爲CEvent類的成員?

class CEvent 
{ 
public: 
    explicit CEvent(LPSECURITY_ATTRIBUTES lpEventAttributes = NULL, 
        BOOL bManualReset = TRUE, 
        BOOL bInitialState = FALSE, 
        LPCTSTR lpName = NULL, 
        bool delete_on_release = true) : 
     handle_(new CHandle(::CreateEvent(lpEventAttributes, 
               bManualReset, 
               bInitialState, 
               lpName), 
           delete_on_release)) 
    { 
    }; 

    BOOL SetEvent() 
    { 
     _ASSERT(NULL != handle_ && NULL != handle_.get()); 
     return ::SetEvent(handle_.get()); 
    }; 

private: 
    boost::shared_ptr<CHandle> handle_; 
}; // class CEvent 

或者,有沒有更好的方法? (請注意,我仍然希望維持由升壓給出的CHandle的複製語義:: shared_ptr的<>。

感謝, PaulH

回答

3

我不會進入討論升壓:: shared_ptr的或任何智能ptr。這裏有幾個原因,爲什麼從不同的角度來看,爲什麼智能指針總是可以被冗餘或打出來?

代碼似乎模仿CLR和NT模型,在這種情況下是由操作系統爲你所做的預定義的語義。它被稱爲:: DuplicateHandle,它運行良好,更適合於跨進程場景(並且會比boo少得多st :: interprocess或類似的)。它適用於其他少數情況。

現在,第二個,希望不是一個矛盾的位置,因爲遏制焦點贏得了regurarly而忽視了老的OO繼承(但是當它爲那些持續尖叫的人玩混音時,它與OO無關:包含我)。所以不管它有多麼罕見,也不管它是OO,非OO還是O(o)的論點:「繼承」在這裏贏得勝利。

爲什麼?因爲它是一個可等待的處理概念,包括Win32事件,互斥鎖,自動重置種類,線程,除了critical_section(它也有深處的後臺處理 - 但在CLR和NT中特別處理,還有它雙重性)。因此它是絕對有意義的:

typedef CHandleT < HANDLE> WaitHandle;

成爲「層次結構」的根,以及底層實現已有的複製語義。

最後,它會最終代表您的數據類型是句柄的最有效表示,因爲它們將模擬您正在定位的操作系統,並且不需要引用計數或雪崩/漣漪引用計數。

然後是跨平臺開發和boost ::線程ING敗壞了牀上時間的故事:-)

+0

+1'DuplicateHandle' – 2009-11-09 21:04:50

+2

@ Majk-a-Ra,爲什麼繼承獲勝?如果他將CHandleT用作「scoped_handle」並且不需要多態性。較少的耦合選項應該是贏家。 – 2009-11-09 22:11:07

+0

它被引用,你提供了正確的關鍵字:組成。相反,混合插入不是耦合。您可以集中更換手柄類型,並做更多。就像標題和模板不耦合。喜歡他們的.cpp的人通常也喜歡遏制:)基於構圖的技術是其中最被低估的技術之一,但是:它在功能性空間中不是問題。面向對象的人們需要更多地質疑,爲什麼不呢。即使在算法中,當然,既沒有用處,也沒有用到,但是用函數形式突出顯示,而不是繼承或包含,不處理多態性。 – 2009-11-09 22:44:10

2

你不需要在手柄的CEvent的存儲爲一個shared_ptr。該句柄已通過CHandleT屬性共享。

只要您不想使用CEvent元素作爲CHandleT元素(使用多態性),組合就很好。