C ++,Union vs Class Inheritance

时间:2012-08-23 15:04:19

标签: c++ class inheritance unions

我遇到了一个问题,我被困在哪种方法比另一种更好:

具有枚举的结构,用于定义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;
 };

4 个答案:

答案 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,您将从后面的上下文中找到它。即使这样,通常也有更简洁的方法来实现它。