在智能指针中安全地包含任意数据

时间:2011-04-01 10:42:20

标签: c++ containers smart-pointers

首先:我搜索了网络的一半以找到this作为最接近的解决方案的答案。然而,这对我来说太重了,但我看起来有点不那么复杂了。

那么,一些上下文:我正在构建一个系统,该系统应该能够处理来自队列的传入消息,然后将这些消息的结果存储在另一个队列中。我想将这些响应存储在泛型类中,因为我将它存储在multimap

响应类目前定义如下

class COutboundMsg  
{  
public:  
    enum eTypeHint {  
        thNone,  
        thSomeType,  
        thLast  
    };  

    eTypeHint m_TypeHint;

    void* m_OutboundData;

    COutboundMsg(COutboundMsg::eTypeHint TypeHint, void* data);
};

COutboundMsg::COutboundMsg(COutboundMsg::eTypeHint TypeHint, void* data) :
m_TypeHint(TypeHint),
m_OutboundData(data)
{
}

现在,目前的工作方式是让用户做这样的事情:

CSomeType* data = new CSomeType();  
COutboundMsg(COutboundMsg::thSomeType , (void*) data);

由另一端的用户将void*强制转换回CSomeType*(使用类型提示)并删除它。

它不喜欢它。

我宁愿将m_OutboundData包含在auto_ptr或其他内容中,并确保在完成后删除它。

有什么想法吗?也许完全不同的方法

3 个答案:

答案 0 :(得分:3)

通常,多态性用于这样的系统;可以放入出站队列的任何项都派生自QueueItem,队列包含QueueItem*或指向QueueItem的智能指针。

由于这些项都来自公共库,因此您可以安全地删除QueueItem*或允许智能指针来处理它。这种方法还允许您使用dynamic_cast来确保指针实际上指向您认为类型的对象。

如果可以采用这种方法,请确保将QueueItem析构函数设为虚拟,否则将不会调用派生类的析构函数。

答案 1 :(得分:2)

shared_ptr存储用于删除对象的删除器,因此不依赖于删除时指针的静态类型。所以这样的事情应该做正确的事情:

COutboundMsg(eTypeHint TypeHint, shared_ptr<void> msg);

shared_ptr<CSomeType> data(new CSomeType);
COutboundMsg(COutboundMsg::thSomeType, data);

答案 2 :(得分:1)

如果事先知道消息集(发送/接收),而不是多态,请考虑变体类型,我将专门讨论boost::variant<>

这种方法的优点是每条消息都是一个特定的类型(我知道你似乎不想实现它 - 但作为一个长期的设计功能,我想你呢'我会发现这种方法是可扩展的,并且该变体描述了一组消息,让我展示一个简单的例子:

假设我有两条消息

struct Logon{}; 
struct Logout{};

我定义了一个变体来保存可能的消息集,在给定的时间它只是其中之一..

typedef boost::variant<Logon, Logout> message_type;

现在我可以将它存储在任何容器中,并像往常一样传递它,唯一的区别是访问它们的真正通用方式是通过访问者,例如。

struct process : boost::static_visitor<>
{
  void operator()(Logon const& cLogon)
  {
    // do stuff
  }
  void operator()(Logout const& cLogout)
  {
    // do stuff
  }
};

// method that processes a given message
void processMessage(message_type const& cMsg)
{
  // don't know what this message is, that's fine, hand it to the visitor
  boost::apply_visitor(process(), cMsg); // the correct overload will be called for the message
}

......我认为它比void*稍好一点;)

相关问题