替换为空*

时间:2012-11-08 17:15:55

标签: c++

我有真实的消息类,例如

class Specific1Message {
   //various functions to get different types of data
};

class Specific2Message {
   //various functions to get different types of data
};

我无法改变。

我正在重写一个编码和解码这些消息的软件工具。它决定在运行时解码/编码哪些消息。

从要重播的文本文件中检索特定消息的负载以模仿真实系统。消息临时存储在std :: list中。为了使新/删除生命周期更加健壮,我被要求使用智能指针。

我对这些消息的第一个想法是做这样的事情: -

class proto_msg : public ref_type {
 public:


}

// ref_type是一个智能指针类

class Specific1msg : public proto_msg {
   public:


  Specific1Message m_msg;  //instance of specific 1 message - composition
};

但是我的工具中有函数,它将proto_msg *作为参数。所以我想要到达Specific1Message(例如)我会这样做:

int SpecificMessageHandler::EncodeMsg(proto_msg* msg, unsigned char* buffer, int size)

但是如何检索一个Specific1Message? msg-> GetMsg() - 但是如何定义这个方法?会有什么回报?

我需要在基类中定义GetMsg()。但是什么是返回类型?那是我无法理解的?或许我需要重新思考。

EDIT 谢谢你的回复。我在其他事情中学到了多次派遣。

最后我决定这样做: -

class realproto {
public:
   const char* getName() const { return "realproto"; }
}; 

class real2ndproto {
public:
   const char* get2Name() const { return "real2ndproto"; }
}; 


template<typename T>
class ProtoWrapper : public ref_type {
public:
   ProtoWrapper(T* real) : m_msg(real) {}
   ~ProtoWrapper() { delete m_msg; }  //cannot have smart ptr on real_proto - so do this way

   T* getMsg() { return m_msg; }

private:
   T* m_msg;
};

然后像这样打电话

  ref_ptr<ProtoWrapper <realproto> > msg2 = new ProtoWrapper<realproto>(new realproto);

  realproto* pr1 = msg2->getMsg(); //if need underlying protocol

这应该允许我删除所需的代码更少的void *。

2 个答案:

答案 0 :(得分:4)

我能想到的唯一选择是模板+双重调度

class proto_msg : public  ref_type{
   public:
      virtual int call_encode (SpecificMessageHandler*, unsigned char* buffer, int size) = 0;
};

template <class M>
class SpecificMesssageTpl : public  proto_msg
 {
   public:
      int call_encode (SpecificMessageHandler* handler, unsigned char* buffer, int size)
      {
          return handler->EncodeMsgSpecific (m_msg, buffer, size);
      }

private:
  M m_msg;  //instance of specific 1 message - composition
};


class SpecificMessageHandler
{
public:
    int SpecificMessageHandler::EncodeMsg(proto_msg* msg, unsigned char* buffer, int size)
   {
        return msg->call_encoder (this, buffer, size);
   }

   int SpecificMessageHandler::EncodeMsgSpecific(Specific1Message * msg, unsigned char* buffer, int size)
   {
    // encode Specific1Message 
   }

   int SpecificMessageHandler::EncodeMsgSpecific(Specific2Message * msg, unsigned char* buffer, int size)
   {
     // encode Specific2Message 
   }
};

答案 1 :(得分:0)

没有一大堆干净,简单的方法可以做到这一点。但是,如果您愿意在略显不雅的代码上妥协,那么有一些可能性。

那么proto_msg如何更新如下:

class proto_msg : public ref_type
{
public:
    virtual int message_type() = 0;
}

它的子类更新如下:

class Specific1msg : public proto_msg
{
public:
    static const int message_id = 1;
    virtual int message_type() { return message_id; }
    Specific1Message m_msg;  //instance of specific 1 message - composition
};

然后你可以使用if语句来选择一个处理程序:

// proto_msg a_message;

if (a_message.message_type() == Specific1msg::message_id)
{
    Specific1msg specific_message = (Specific1msg)a_message;
    // do something with specific_message.msg
}

实际上,C ++确实以运行时类型信息或RTTI的形式支持一些简单的内省功能。默认情况下,这不一定会编译到您的二进制文件中;它可能需要额外的编译器标志(GNU land中的-frtti)。 RTTI允许您使用dynamic_cast执行类型转换操作,可以正常处理故障。

// proto_msg* a_message

Specific1Message* specific_message = dynamic_cast<Specific1Msg*>(a_message));

if (message != nullptr)
{
    // Do something with specific_message.msg
}

等等。还有很多其他方法可以做到这一点,我认为总的来说我更喜欢Aleguna的双重调度模板魔法,但这种机制应该是非常直接的,对任何人来说都很简单!

代码未经测试,未编译,E&amp; OE等; - )