结合C++11的新特性来解析C++中的枚举与联合

2020-01-06 14:21:27刘景俊


union [name] { member-list };

参数
name
为联合提供的类型名称。
member-list
联合可以包含的成员。 请参阅“备注”。
备注
声明联合
利用 union 关键字开始联合的声明,并用大括号包含成员列表:


// declaring_a_union.cpp
union RecordType  // Declare a simple union type
{
  char  ch;
  int  i;
  long  l;
  float f;
  double d;
  int *int_ptr;
}; 
int main()
{
  RecordType t;
  t.i = 5; // t holds an int
  t.f = 7.25 // t now holds a float 
}

使用联合
在前面的示例中,任何访问联合的代码都需要了解保存数据的成员。 此问题最常见的解决方案是将联合以及其他枚举成员(指示当前存储在联合中的数据的类型)放入一个结构中。 这称为可区分的联合,下面的示例演示了基本模式。


#include "stdafx.h"
#include <queue>

using namespace std;


enum class WeatherDataType
{
  Temperature, Wind
};

struct TempData
{
  int StationId;
  time_t time;
  double current;
  double max;
  double min;
};

struct WindData
{
  int StationId;
  time_t time;
  int speed;
  short direction;
};

struct Input
{
  WeatherDataType type;
  union
  {
    TempData temp;
    WindData wind;
  };
};

// Functions that are specific to data types
void Process_Temp(TempData t) {}
void Process_Wind(WindData w) {}

// Container for all the data records
queue<Input> inputs;
void Initialize();


int main(int argc, char* argv[])
{
  Initialize();
  while (!inputs.empty())
  {
    Input i = inputs.front();
    switch (i.type)
    {
    case WeatherDataType::Temperature:
      Process_Temp(i.temp);
      break;
    case WeatherDataType::Wind:
      Process_Wind(i.wind);
      break;
    default:
      break;
    }
    inputs.pop();

  }
  return 0;
}

void Initialize()
{
  Input first, second;
  first.type = WeatherDataType::Temperature;
  first.temp = { 101, 1418855664, 91.8, 108.5, 67.2 };
  inputs.push(first);

  second.type = WeatherDataType::Wind;
  second.wind = { 204,1418859354, 14, 27 };
  inputs.push(second);
}

 

 

在前面的示例中,请注意 Input 结构中的联合没有名称。 这是匿名联合,可以访问其成员,如同它们是结构的直接成员一样。 有关匿名联合的详细信息,请参阅下面一节。
当然,上面的示例演示的问题也可以通过以下方法解决:使用派生自公共基类的类,并基于容器中每个对象的运行时类型对代码进行分支。 这可以生成更易于维护和理解的代码,但是也可能比使用联合更慢。 此外,通过联合可以存储完全不相关的类型,并动态更改存储的值的类型,而无需更改联合变量本身的类型。 因此可以创建其元素存储不同类型的不同值的 MyUnionType 异类数组。