2016-12-27 26 views
1

在标题中总结问题很难;所以让我澄清这里的情况。具有互斥数据成员的对象的设计替代方案

我有我设计一个代表BER TLV structure类。在本规范中,TLV的“数据”部分可以包含原始字节的数据或其他嵌套的TLV。为了支持这两种形式,我用的是相同的结构,但两个载体(只有一个实际上将包含什么,这取决于我们发现为我们解析TLV数据):

class BerTlv 
{ 
public: 

    void Parse(std::vector<std::uint8_t> const& bytes_to_parse); 

    // Assume relevant accessors are provided 

private: 

    // Will be m_data or m_nestedTlvs, but never both 
    std::vector<std::uint8_t> m_data; 
    std::vector<BerTlv> m_nestedTlvs; 
}; 

从外面看,在此之后的对象是完全构建(所有TLV数据解析),用户将需要检测他们正在处理的数据类型。基本上,他们必须检查m_data.empty(),如果是这样,请使用m_nestedTlvs。我对这种方法并不满意,它闻起来像缺乏更好的设计。

我觉得某种形式的工会的,虽然我不觉得,因为矢量数据堆中分配一个真正的联盟将是适当的在这里。于是我想到了std::variant

std::vector<std::variant<BerTlv, std::uint8_t>> m_data; 

不过,我担心这种负面影响,因为该std::uint8_t情况下是真的只是个字节的数据。它现在也会变得不连续。该变体仅对嵌套的TLV情况有益,而不是太多。

接下来,我认为在这里使用访问者模式,但我不能完全可视化的界面看起来像什么或如何,这将提高在两种情况下的可用性(原始数据VS嵌套的TLV)。访客是否是正确的解决方案?

没事我以为至今感觉对了,所以我希望在一个更好的设计方法对这个问题的反馈。这里的一般问题是有数据成员有时未被使用或互斥。这也是我在其他情况下遇到的一个问题,因此,对这样的问题采取一般设计方法会很好。

请注意,我有机会获得C++ 14层的功能及以下。

+0

而不是有两个不同的值的向量,你有没有考虑使用一个单一的字节向量,再加上一个引用部分向量的树? –

+0

@VaughnCato:你的意思是一棵指向矢量偏移量的树?当你最终得到一个嵌套TLV的复杂树时,我不明白这是如何工作的。这个类的部分职责是从用户中提取“字节数组”,并提供完整的,可用的类型和对象。也想避免解析后建设。 –

+0

不知道工会联盟有什么问题std :: vector m_data; std :: vector m_nestedTlvs; }内容;并记住在enum之外的枚举中的实际类型 – Oncaphillis

回答

3

基本上,他们必须检查m_data.empty(),如果是,则使用m_nestedTlvs。

如果想法是一个对象要么有一个字节数组要么有一个其他对象数组,那么这就是你应该使用的变体:variant<vector<std::uint8_t>, vector<BerTlv>>。 A vectorvariant s与您指定的用例不符。

+0

我做了一个错误的假设,即“变体”是用C++ 14提供的,但事实并非如此。它是C++ 17的一部分。所以我想变体是不可能的。 –

+0

'boost :: variant'? –

+0

是的,我有提升。所以没关系;) –