很难在标题中总结问题;所以请允许我澄清一下这里的情况。
我正在设计一个代表 BER TLV structure 的类.在本规范中,TLV 的“数据”部分可以包含数据的原始字节或其他嵌套的 TLV。为了支持这两种形式,我使用了相同的结构,但有两个 vector (实际上只有一个 vector 包含某些内容,具体取决于我们在解析 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
。我对这种方法不是很满意;闻起来好像缺少更好的设计。
我想到了某种形式的 union ,尽管我认为真正的 union 在这里不合适,因为 vector 数据是堆分配的。于是想到了std::variant
:
std::vector<std::variant<BerTlv, std::uint8_t>> m_data;
但是,我担心这会对 std::uint8_t
情况产生负面影响,因为它实际上只是字节数据。它现在也将变得不连续。该变体仅对嵌套的 TLV 案例有利,而且获益不大。
接下来我考虑在这里使用访问者模式,但我无法完全想象界面的外观或这将如何提高两种情况下的可用性(原始数据与嵌套 TLV)。访问者是正确的解决方案吗?
到目前为止,我的想法都不对,所以我希望就此问题的更好设计方法提供反馈。这里的一般问题是数据成员有时未被使用或相互排斥。这也是我在其他情况下遇到的一个问题,所以如果有一个通用的设计方法来解决这样的问题就太好了。
请注意,我可以访问 C++14 及以下功能。
最佳答案
Basically, they'd have to check m_data.empty(), and if so, use m_nestedTlvs.
如果想法是一个对象要么有一个字节数组,要么有一个其他对象数组,那么这就是您应该使用的变体:variant<vector<std::uint8_t>, vector<BerTlv>>
. vector
的 variant
s 与您指定的用例不匹配。
关于c++ - 具有互斥数据成员的对象的设计替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41349511/