2009-11-09 91 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元素(使用多态性),组合就很好。