C++ C++;,并集与类继承

C++ C++;,并集与类继承,c++,class,inheritance,unions,C++,Class,Inheritance,Unions,我有一个特定的问题,我被哪种方法比另一种更好所困扰: 具有枚举的结构,该枚举定义联合成员或 一组具有继承性的类 示例代码如下所示: 基于工会的结构 typedef union TokenValue{ bool bValue; long lvalue; double dvalue; std::string svalue; } class Token{ public: TokenType type; TokenValue value; }

我有一个特定的问题,我被哪种方法比另一种更好所困扰:

具有枚举的结构,该枚举定义联合成员或 一组具有继承性的类

示例代码如下所示:

基于工会的结构

  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;
 };
类继承

  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;
 };

如果其中一个/或:默认情况下,您应该支持继承。工会可能存在风险,而且很容易被滥用。该语言在继承方面具有良好的语法和语义

这种联合的一般问题是,您必须定义大量的实现细节,这些细节通常是从您那里抽象出来的——构造、销毁、模式、活动成员


正如评论所建议的,您应该详细说明您的问题,以获得更具体的解决方案。

您的类
令牌
实现了所谓的“歧视性联合”。但它的成员不应该公开;这使得在不更新类型标志的情况下更改联合中存储的类型太容易了。相反,提供重载访问器来存储和读取值。存储
bool
值的访问者也应设置类型标志;对于其他访问器,

几乎总是继承是C++中的首选方法。我认为最好使用并集的唯一情况是,数据采用相同数量的位,但您还不知道解释这些位的正确方法。例如,您正在从套接字读取原始比特流,该套接字可以是有符号或无符号int,您将在后面的上下文中找到它。即使如此,通常也有更干净的方法来实现它。

这种类型的设计被称为一种。您可以通过谷歌搜索“C++鉴别力联盟”来查看这类设计的几个示例和方法

代码>联合< /COD>通常被认为是C++的低级和不安全的。同样,基于
union
的解决方案应该提供访问器,而不是直接暴露不安全的
union
成员<代码>联合s还有一个缺点,在C++11之前,它们不能包含非POD数据结构(因此没有
std::string

基于继承的解决方案的优点是可以开始使用多态性(例如,添加虚拟的
PrintTo
方法)。(当然,您可以通过将
PrintTo
方法添加到基于
union
的解决方案中来实现类似的结果,该解决方案在
TokenType
上进行
切换,但这不是OO。)

基于
union
的解决方案可能比基于继承的解决方案(无
vtable
)更轻。对于lexer标记这样的低级标记,这可能更可取


如果允许第三方库,我强烈建议查看一个更为C++的区分工会的方法。

你要达到什么目标?你想达到什么?在格式化代码时忽略一些语法错误,除非你提到你要用它做什么,没有人能更好地帮助您。这是一段来自手写词法分析器的代码。基本上是一个对象/结构,它有一个成员,根据类型告诉哪些数据成员可用。它可以通过继承和使用union alsoI'm在制作编译器的过程中完成。我采用了基于工会的方法(当然,这里的方法太简单了,需要做一些修改)。我确实尝试过使用基于继承的解决方案,但这似乎太费劲了,而且不如基于联合的解决方案有效。我已经看到一些答案,人们说不要使用工会,它们是糟糕的废话。我只想告诉他们一件事:不要盲目遵守任何规则。仔细考虑你的项目需求。