C++ 使用多态性时如何避免向下转换?

C++ 使用多态性时如何避免向下转换?,c++,inheritance,design-patterns,static-cast,C++,Inheritance,Design Patterns,Static Cast,考虑以下设计: class RawDataBase { private: std::string data; }; class RawDataA : public RawDataBase { private: int spec_data_for_a1; int spec_data_for_a2; }; class RawDataB : public RawDataBase { private: int spec_data__for_b;

考虑以下设计:

class RawDataBase
{
private:    
    std::string data;
};

class RawDataA : public RawDataBase
{
private:    
    int spec_data_for_a1;
    int spec_data_for_a2;
};

class RawDataB : public RawDataBase
{
private:    
    int spec_data__for_b;
};

class MessageBase
{
private:    
    int x;
    int y;
    int z;
public:
    virtual void Decode(RawDataBase *raw)
    {
        // extract x,y,z from raw.data
    }
};

class MessageA : public MessageBase
{
private:    
    int spec_data_for_a1;
    int spec_data_for_a2;
public:
    /* Here raw must be RawDataA*/
    virtual void Decode(RawDataBase *raw)
    {
        MessageBase::Decode(raw);
        RawDataA raw_data = static_cast<RawDataA*>(raw);
        // extract spec_data_for_a1, spec_data_for_a2 from raw_data
    }
};

class MessageB : public MessageBase
{
private:    
    int spec_data__for_b;
public:
    /* Here raw must be RawDataB*/
    virtual void Decode(RawDataBase *raw)
    {
        MessageBase::Decode(raw);
        RawDataB raw_data = static_cast<RawDataB*>(raw);
        // extract spec_data__for_b from raw_data       
    }
};
类数据库
{
私人:
std::字符串数据;
};
类RawDataA:公共RawDataBase
{
私人:
用于a1的内部规范数据;
用于a2的内部规范数据;
};
类RawDataB:公共RawDataBase
{
私人:
用于b的内部规范数据;
};
类消息库
{
私人:
int x;
int-y;
intz;
公众:
虚拟无效解码(RAWDABASE*raw)
{
//从原始数据中提取x、y、z
}
};
MessageA类:公共MessageBase
{
私人:
用于a1的内部规范数据;
用于a2的内部规范数据;
公众:
/*这里raw必须是RawDataA*/
虚拟无效解码(RAWDABASE*raw)
{
MessageBase::解码(原始);
RawDataA raw_data=静态_cast(raw);
//从原始_数据中提取_a1的规格数据_、_a2的规格数据_
}
};
类MessageB:公共MessageBase
{
私人:
用于b的内部规范数据;
公众:
/*这里raw必须是RawDataB*/
虚拟无效解码(RAWDABASE*raw)
{
MessageBase::解码(原始);
RAWDAB raw_data=静态_转换(raw);
//从原始数据中提取规格数据
}
};
在将
原始数据
解码为
消息
时,我遇到了一个设计问题

有两种类型的
RawData
RawDataA
&
RawData
RawDataA
将被解码为
MessageA
,而
RawDataB
将被解码为
MessageB
RawDataA
RawDataB
都共享一些公共数据,因此创建了
RawDataBase
作为基类。 从
MessageBase
派生的
MessageA
MessageB
也是如此

然后,在
MessageBase
中添加一个虚拟
Decode
函数,并将
RawDataBase
对象作为参数。但是
MessageA中存在一些问题
和
消息b
。对于
MessageA
,参数实际上应该始终是
RawDataA
,因此必须在此处进行向下转换。但有人说,在代码中使用向下转换时,一定存在一些设计问题

所以我的问题是如何在这里设计代码以避免向下转换


谢谢

为避免在此处向下投射:

class MessageA : public MessageBase {
    virtual void Decode(RawDataBase *raw) { ...}
}
您的代码必须是这样的:

class MessageA : public MessageBase {
    virtual void Decode(RawDataA *raw) { ...}
}
这意味着
MessageBase
必须以某种方式成为:

class MessageBase {
    virtual void Decode(RawDataA *raw){...}
}
这可以使用如下模板完成:

class RawDataBase { /* ... */ };
class RawDataA : public RawDataBase { /* ... */ }; 
class RawDataB : public RawDataBase { /* ... */ };

template<typename T>
class MessageBase {

    using RawDataType = T;

    // ...

    virtual void Decode(RawDataType *raw){/* ... */}

    // ...

};

class MessageA : public MessageBase<RawDataTypeA> {
    // ...

    virtual void Decode(RawDataType *raw){/* ... */}

    // ...
};

class MessageB : public MessageBase<RawDataTypeB> {
    // ...

    virtual void Decode(RawDataType *raw){/* ... */}

    // ...
};
类数据库{/*…*/};
类RawDataA:公共RawDataBase{/*…*/};
类RawDataB:公共RawDataBase{/*…*/};
模板
类消息库{
使用RawDataType=T;
// ...
虚拟空解码(RawDataType*raw){/*…*/}
// ...
};
MessageA类:公共MessageBase{
// ...
虚拟空解码(RawDataType*raw){/*…*/}
// ...
};
类MessageB:公共MessageBase{
// ...
虚拟空解码(RawDataType*raw){/*…*/}
// ...
};

模板
在分解代码方面似乎比继承更好。你是说CRTP吗?或者其他解决方案。谢谢不需要CRTP,一个简单的模板类。酷!!这解决了我的问题:-)谢谢你的帮助!它不是CRTP,它将用于
类派生:公共基
。这是模板类的简单继承。@Jarod42你说得对,我的错。我编辑了我的答案。Thx:)