如何删除这种开关盒?

时间:2014-09-21 01:20:58

标签: c++

我希望通用大量内存,可能从二进制文件加载,并且消息ID已知,我需要为每个内存块创建新实例。做这个的最好方式是什么?

目前的情况是我需要将每个新添加的消息类型添加到以下切换案例中。

struct Message1;
struct Message2;

void UnSerialize(int messageId, void* data) {
    switch (messageId) {
    case MESSAGE1:
        Message1* m1 = new Message1;
        std::memcpy(m1, data, sizeof(Message1));
        m1.dump();
        delete m1;
        break;
    case MESSAGE2:
        Message2* m2 = new Message2;
        std::memcpy(m2, data, sizeof(MESSAGE2));
        m2.dump();
        delete m2;
        break;
    default:
        std::cout << "Unknown Message Type.";
        break;
    }
}

我可以在C ++中写下面的内容吗?没有C ++ 11和boost吗?

MessageTypeList tl;
tl.append(Message1);
tl.append(Message2);
void UnSerialize(MessageTypeList tl, int messageId, void* data) {
{
    foreach( type t : tl ) {
        if (t::id == MessageId) {
            t instance = new t;
            memcpy(t, data, sizeof(t));
            instance.dump();
            delete instance;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我不确定您要执行的操作,但如果您只想从DumpMessage1结构调用Message2函数,则可以执行以下操作:

struct BaseMessge
{
    virtual void Dump() = 0;
};
struct Message1 : public BaseMessage
{
    void Dump()
    {
        //Your code
    }
};
struct Message2 : public BaseMessage
{
    void Dump()
    {
        //Your code
    }
};

void UnSerialize(BaseMessage *Message)
{
    Message->Dump();
}

答案 1 :(得分:-1)

有一些方法可以表达对的列表(类型,ID),并为每种类型或ID实现所需的任何行为。但是,我认为切换仍然是一个非常好的方法 - 在任何方法中,你必须列出所有类型soomehow - 但让每个案例中的代码成为模板函数。

template <class T>
void UnSerialize(void* data) {
    static_assert(std::is_trivially_copyable<T>::value,
                  "Message class is not trivally copyable");
    T message;
    memcpy(&message, data, sizeof(T));
    message.dump();
}

void UnSerialize(int messageId, void* data) {
    switch (messageId) {
    case MESSAGE1:
        UnSerialize<Message1>(data);
        break;
    case MESSAGE2:
        UnSerialize<Message2>(data);
        break;
    default:
        std::cout << "Unknown Message Type.";
        break;
    }
}

请注意,我已在每种情况下为代码建议了不同的实现:

  • 没有动态分配,消息在函数的本地变量中分配。
  • 添加了一个静态断言,memcpy将按预期工作。

另一种避免switch的方法是使用虚方法构建一对ID和辅助类实例的数组。每个实例都来自派生的模板类,该模板类使用该案例中的代码实现该虚拟方法。然后,你只需要静态地构建该数组(我建议使用std::unique_ptr来保存指向辅助类的指针)。

请注意,编写该数组与编写switch非常相似,只是让您的代码更难阅读。