我遇到了一个问题,我被困在哪种方法比另一种更好:
具有枚举的结构,用于定义union成员OR中的数据 一组具有继承的类
示例代码如下:
基于联盟的结构
typedef union TokenValue{
bool bValue;
long lvalue;
double dvalue;
std::string svalue;
}
class Token{
public:
TokenType type;
TokenValue value;
};
类继承
class TokenBase{
public:
TokenType type;
};
class TokenNumber: public TokenBase{
public:
bool isInt;
long lvalue;
double dvalue;
};
class TokenString: public TokenBase{
public:
std::string svalue;
};
答案 0 :(得分:4)
你的班级Token
实现了所谓的“歧视联盟”。但其成员不应公开;这使得在不更新类型标志的情况下更改存储在union中的类型变得非常容易。相反,提供重载的访问器来存储和读取值。存储bool
值的访问器也应设置类型标志;同样适用于其他访问者。
答案 1 :(得分:4)
这种类型的设计称为discriminated union or tagged union。您可以通过Google“C ++辨别联盟”来查看此类设计的几个示例和方法。
C union
通常被认为有点低级且对C ++不安全。在Pete Becker said时,基于union
的解决方案应该提供访问者,而不是直接暴露不安全的union
成员。 union
还有一个缺点,就是在C ++ 11之前,它们不能包含非POD数据结构(所以没有std::string
)。
基于继承的解决方案的优点是您可以开始使用多态(例如,添加虚拟PrintTo
方法)。 (当然,您可以通过向基于PrintTo
的解决方案添加union
方法来完成类似的结果,该解决方案switch
超过TokenType
,但这不是OO。 )
基于union
的解决方案可能比基于继承的解决方案更轻(无vtable
)。对于像词法分析器这样低级别的东西,这可能是最好的。
如果允许使用第三方库,我强烈建议您查看Boost.Variant以获取更多C ++方法来区分工会。
答案 2 :(得分:0)
如果是/或:默认情况下,您应该支持继承。工会可能存在风险,容易被滥用。该语言在继承方面具有良好的语法和语义。
这个联合的一般问题是你必须定义大量的实现细节,这些细节通常是从你那里抽象出来的 - 构造,破坏,模式,活跃成员......
正如评论所示 - 您应该详细说明您的问题以获得更具体的解决方案。
答案 3 :(得分:0)
几乎总是,继承是C ++中的首选方法。我可以想到一个首选联合的唯一情况是数据占用相同的位数,但是你还不知道解释这些位的正确方法。例如,您正在从套接字读取一个原始的位流,该套接字可以是有符号或无符号的int,您将从后面的上下文中找到它。即使这样,通常也有更简洁的方法来实现它。