在标题中总结问题很难;所以让我澄清这里的情况。具有互斥数据成员的对象的设计替代方案
我有我设计一个代表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层的功能及以下。
而不是有两个不同的值的向量,你有没有考虑使用一个单一的字节向量,再加上一个引用部分向量的树? –
@VaughnCato:你的意思是一棵指向矢量偏移量的树?当你最终得到一个嵌套TLV的复杂树时,我不明白这是如何工作的。这个类的部分职责是从用户中提取“字节数组”,并提供完整的,可用的类型和对象。也想避免解析后建设。 –
不知道工会联盟有什么问题std :: vector m_data; std :: vector m_nestedTlvs; }内容;并记住在enum之外的枚举中的实际类型 –
Oncaphillis