【问题标题】:Best way to change from base class to derived class从基类更改为派生类的最佳方法
【发布时间】:2013-06-07 09:53:22
【问题描述】:

我知道在这个论坛上以各种方式提出了这个问题,但我仍然无法弄清楚我需要做什么的最佳方式(在阅读了各种其他帖子之后)。所以我决定寻求进一步的建议!

我有一个消息类层次结构,类似于(省略大部分细节):

class MsgBase
{
    public:
        uint8_t getMsgType(void);

    protected: // So that derived classes can access the member
        char _theMsgData[100];
}

class MsgType1 : public MsgBase
{
}

class MsgType2 : public MsgBase
{
}

所以我收到了一个消息数据块,我用它来创建我的消息。但是在我读出消息类型之前,我不知道要创建哪个消息。所以我最终得到:

MsgBase rxMsg(rxData);
if (rxMsg.getMsgType() == 1)
{
    // Then make it a MsgType1 type message
}
else if (rxMsg.getMsgType() == 2)
{
    // Then make it a MsgType2 type message
}

这是我坚持的一点。根据我的阅读,我无法从基础动态转换为派生。所以我目前的选择是实例化一个全新的派生类型(这似乎效率低下),即:

if (rxMsg.getMsgType() == 1)
{
    // Now use the same data to make a MsgType1 message.
    MsgType1 rxMsg(rxData);
}

有没有一种方法可以将数据视为基类,以便确定其类型,然后将其“变形”为所需的派生类型?

谢谢, 饲料

【问题讨论】:

  • getMsgType 是如何工作的?
  • 当您实例化一个类(任何类型)时,数据存储在基类成员 char _theMsgData[] 中。然后 getMsgType 读出包含消息类型值的特定元素并返回一个整数。例如它的实现可能是这样的:return _theMsgData[1];
  • 所有相关信息似乎都在变量rxData中。所以请向rxData 询问类型信息。
  • 谢谢 :) 我知道,我可以这样做......但 rxData 是一个“愚蠢”的容器,不知道在哪里看。我想使用一个“知道”消息类型的函数......如果可能的话。但是,问题是我想以一种好的方式做些什么?
  • 不知何故,有时您必须从哑容器中提取类型。您应该在创建具体消息对象之前执行此操作。

标签: c++ base derived


【解决方案1】:

rxData 是什么?我假设它只是一个数据块,您应该在创建任何消息对象之前对其进行解析以确定消息类型。根据消息数据是否始终具有相同的长度,您应该考虑使用std::arraystd::vector 来传递数据块。

typedef std::vector<char> MsgDataBlob;

class MsgBase
{
    public:
        uint8_t getMsgType();
        MsgBase(MsgDataBlob blob) : _theMsgData(std::move(blob)) {}

    protected: // So that derived classes can access the member
        MsgDataBlob _theMsgData;
};

//derived classes here...

//this could be either a free function or a static member function of MsgBase:
uint8_t getMessageType(MsgDataBlob const& blob) { 
  // read out the type from blob
}

std::unique_ptr<MsgBase> createMessage(MsgDataBlob blob) {
  uint8_t msgType = getMessageType(blob);
  switch(msgType) {
    case 1: return make_unique<MsgDerived1>(std::move(blob));
    case 2: return make_unique<MsgDerived2>(std::move(blob));
    //etc.
  }
}

【讨论】:

  • hmmm...我喜欢您在那里所做的事情:) 我会试一试并回复您,谢谢 :) (是的,您的假设是正确的...只是一个 blob。 ..lol)
  • 这叫做工厂方法模式,你可能想查一下;)
  • 哦,是的 :) 我没有将其识别为工厂,我完全错了!效果很好,非常感谢。
【解决方案2】:

如果您希望消息返回数据,但例如 MsgType1 应该全部小写,而 MsgTyp2 全部大写,您可以在 MsgBase 中创建一个虚函数,例如,

virtual char *getData();

并且这个函数应该在子类中重新实现,这样它就可以对数据做你想让它做的事情。这样,当您在基类指针上调用此函数时,您将获得重新实现的功能,具体取决于调用时实际指针的类型。

【讨论】:

  • 有趣,谢谢你的回复。但对我来说并不是那么简单:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 2014-03-17
  • 2016-08-30
相关资源
最近更新 更多