考虑以下设计:
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
}
};
将
RawData
解码为Message
时遇到设计问题。RawData
有两种类型(RawDataA
和RawDataB
)。 RawDataA
将解码为MessageA
,而RawDataB
将解码为MessageB
。 RawDataA
和RawDataB
都共享一些公共(public)数据,因此RawDataBase
被创建为基类。从
MessageA
派生的MessageB
和MessageBase
也是如此。然后,将一个虚拟
Decode
函数添加到MessageBase
中,以RawDataBase
对象作为参数。但是MessageA
中存在一些问题和
MessageB
。对于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){/* ... */}
// ...
};
关于c++ - 使用多态性时如何避免下投?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45608133/