2017-08-10 76 views
1

考虑下面的设计:如何在使用多态性时避免下滑?

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  
    } 
}; 

我有一个设计问题,而解码RawDataMessage

RawDataRawDataA & RawDataB)有两种类型。 RawDataA将被解码为MessageA,而RawDataB将被解码为MessageBRawDataARawDataB都共享一些常用数据,因此RawDataBase被创建为基类。 同样适用于MessageAMessageB,源自。

然后,将一个虚拟Decode函数添加到中,以RawDataBase对象作为参数。但在MessageAMessageB中有一些问题。对于MessageA,参数实际上应该始终为RawDataA,因此必须在此完成压铸。但是有人说,在代码中使用下拉式演员时必定存在一些设计问题。

所以我的问题是如何设计这里的代码,以避免羽绒被?

谢谢!

+0

'模板'似乎比继承在这里更好分解代码。 – Jarod42

+0

你是否也指CRTP?或其他解决方案。谢谢! – xYZ

+0

不需要CRTP,一个简单的模板类。 – Jarod42

回答

1

为了在这里避免停机投:

class MessageA : public MessageBase { 
    virtual void Decode(RawDataBase *raw) { ...} 
} 

您的代码必须成为这样的事情:

class MessageA : public MessageBase { 
    virtual void Decode(RawDataA *raw) { ...} 
} 

这意味着必须以某种方式成为:

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){/* ... */} 

    // ... 
}; 
+0

酷!这解决了我的问题:-)感谢您的帮助! – xYZ

+0

它不是CRTP,它将用于'class Derived:public Base '。这是模板类的简单继承。 – Jarod42

+0

@ Jarod42你是对的,我的坏。我编辑了我的答案。谢谢 :) – wasthishelpful