5

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

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

示例代码如下:

基于联合的结构

  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

4 回答 4

7

这种类型的设计称为有区别的联合或标记联合。您可以在 Google 上搜索“C++ 有区别的联合”以查看此类设计的几个示例和方法。

ACunion通常被认为对 C++ 来说有点低级和不安全。正如Pete Becker 所说union基于您的解决方案应该提供访问器,而不是直接暴露不安全的union成员。 unions 还有一个缺点,在 C++11 之前,它们不能包含非 POD 数据结构(所以 no std::string)。

基于继承的解决方案的优点是您可以开始使用多态性(例如,添加一个虚拟PrintTo方法)。(当然,您可以通过向基于 - 的解决方案添加一个PrintTo方法来完成类似的结果,但这是非 OO 的。)unionswitchTokenType

基于-union的解决方案可能比基于继承的解决方案更轻量级(否vtable)。对于像词法分析器令牌这样的低级事物,这可能更可取。

如果允许使用第三方库,我强烈建议您查看Boost.Variant以获得更多 C++ 方法来区分联合。

于 2012-08-23T15:16:27.877 回答
4

你的班级Token实现了所谓的“有区别的联合”。但是它的成员不应该是公开的;这使得在不更新类型标志的情况下更改存储在联合中的类型变得太容易了。相反,提供重载的访问器来存储和读取值。存储bool值的访问器也应该设置类型标志;对于其他访问者也是如此。

于 2012-08-23T15:13:45.663 回答
0

if any/or: 默认情况下,您应该支持继承。工会可能存在风险并且容易被滥用。该语言在继承方面具有良好的语法和语义。

这个联合的普遍问题是你必须定义大量的实现细节,这些细节通常是从你那里抽象出来的——构造、销毁、模式、活动成员……</p>

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

于 2012-08-23T15:09:30.257 回答
0

几乎总是,继承是 C++ 中的首选方法。我能想到的唯一首选联合的情况是数据采用相同数量的位,但您还不知道解释这些位的正确方法。例如,您正在从可能是有符号或无符号 int 的套接字中读取原始位流,您将在后面的上下文中找到它。即使这样,通常也有更简洁的方法来实现它。

于 2012-08-23T15:15:52.750 回答