• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 结合C++11的新特性来解析C++中的枚举与联合

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

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++11新特性,c++三大特性,c++特性,c++枚举类型的用法,c++枚举等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

枚举
枚举是用户定义的类型,其中包含一组称为枚举器的命名的整型常数。
语法

// unscoped enum:
enum [identifier] [: type]

{enum-list}; 

// scoped enum:
enum [class|struct] 
[identifier] [: type] 
{enum-list};
// Forward declaration of enumerations (C++11):
enum A : int; // non-scoped enum must have type specified
enum class B; // scoped enum defaults to int
enum class C : short;

</div>

参数
identifier
指定给与枚举的类型名称。
type
枚举器的基础类型;所有枚举器都具有相同的基础类型。可能是任何整型。
enum-list
枚举中以逗号分隔的枚举器列表。范围中的每个枚举器或变量名必须是唯一的。但是,值可以重复。在未区分范围的枚举中,范围是周边范围;在区分范围的枚举中,范围是 enum-list 本身。
class
可使用声明中的此关键字指定枚举区分范围,并且必须提供 identifier。还可使用 struct 关键字来代替 class,因为在此上下文中它们在语义上等效。
备注
枚举提供上下文来描述以命名常数表示的一系列值,这些值也称为枚举器。在原始 C 和 C++ 枚举类型中,非限定枚举器在声明枚举的整个范围中可见。在区分范围的枚举中,枚举器名称必须由枚举类型名称限定。以下示例演示两种枚举之间的基本差异:

namespace CardGame_Scoped
{
  enum class Suit { Diamonds, Hearts, Clubs, Spades };

  void PlayCard(Suit suit)
  {
    if (suit == Suit::Clubs) // Enumerator must be qualified by enum type
    { /*...*/}
  }
}

namespace CardGame_NonScoped
{
  enum Suit { Diamonds, Hearts, Clubs, Spades };

  void PlayCard(Suit suit)
  {
    if (suit == Clubs) // Enumerator is visible without qualification
    { /*...*/
    }
  }
}

</div>

将为枚举中的每个名称分配一个整数值,该值与其在枚举中的顺序相对应。默认情况下,为第一个值分配 0,为下一个值分配 1,以此类推,但你可以显式设置枚举器的值,如下所示:

enum Suit { Diamonds = 1, Hearts, Clubs, Spades };

</div>

为枚举器 Diamonds 分配值 1。后续枚举器接收的值会在前一个枚举器的值的基础上加一(如果没有显式赋值)。在前面的示例中,Hearts 将具有值 2,Clubs 将具有值 3,依此类推。
每个枚举器将被视为常数,并且必须在定义 enum 的范围内(对于未区分围的枚举)或在枚举本身中(对于区分范围的枚举)具有唯一名称。为这些名称指定的值不必是唯一的。例如,如果一个未区分范围的枚举 Suit 的声明如下:

enum Suit { Diamonds = 5, Hearts, Clubs = 4, Spades };
</div>

Diamonds、Hearts、Clubs 和 Spades 的值分别是 5、6、4 和 5。请注意,5 使用了多次;尽管这并不符合预期,但是允许的。对于区分范围的枚举来说,这些规则是相同的。
强制转换规则
未区分范围的枚举常数可以隐式转换为 int,但是 int 不可以隐式转换为枚举值。下面的示例显示了如果尝试为 hand 分配一个不是 Suit 的值可能出现的情况:

int account_num = 135692;
Suit hand;
hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'

</div>

将 int 转换为区分范围或未区分范围的枚举器时,需要强制转换。但是,你可以将区分范围的枚举器提升为整数值,而不进行强制转换。

int account_num = Hearts; //OK if Hearts is in a unscoped enum
</div>

按照这种方式使用隐式转换可能导致意外副作用。若要帮助消除与区分范围的枚举相关的编程错误,区分范围的枚举值必须是强类型值。区分范围的枚举器必须由枚举类型名称(标识符)限定,并且无法进行隐式转换,如以下示例所示:

namespace ScopedEnumConversions
{
  enum class Suit { Diamonds, Hearts, Clubs, Spades };

  void AttemptConversions()
  {
    Suit hand; 
    hand = Clubs; // error C2065: 'Clubs' : undeclared identifier
    hand = Suit::Clubs; //Correct.
    int account_num = 135692;
    hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'
    hand = static_cast<Suit>(account_num); // OK, but probably a bug!!!

    account_num = Suit::Hearts; // error C2440: '=' : cannot convert from 'Suit' to 'int'
    account_num = static_cast<int>(Suit::Hearts); // OK
}

</div>

注意,hand = account_num; 行仍会导致对未区分范围的枚举发生的错误,如前面所示。它可以与显式强制转换一起使用。但是,借助区分范围的枚举,不再允许在没有显式强制转换的情况下在下一条语句 account_num = Suit::Hearts; 中尝试转换。

联合

union 是用户定义的类型,其中所有成员都共享同一个内存位置。 这意味着在任何给定时间,联合都不能包含来自其成员列表的多个对象。 这还意味着无论联合具有多少成员,它始终仅使用足以存储最大成员的内存。
具有大量对象和/或内存有限时,联合可用于节省内存。 但是,需要格外小心才能正确使用它们,因为由你负责确保可始终访问写入的最后一个成员。 如果任何成员类型具有不常用构造函数,则必须编写附加代码来显式构造和销毁该成员。 使用联合之前,应考虑是否可以使用基类和派生类来更好地表示尝试解决的问题。

union [name] { member-list };
</div>

参数
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 
}
</div>

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

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

</div>


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

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C++ 11和C++98相比有哪些新特性
  • C++11新特性中auto 和 decltype 区别和联系
  • C++11新特性之auto的使用
  • C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)
  • C++11的新特性简单汇总介绍 (二)
  • C++11的新特性简单汇总介绍 (一)
  • C++11的for循环,以及范围Range类的简单实现
  • 关于C++一些特性的探究
  • 结合C++11新特性来学习C++中lambda表达式的用法
  • 结合C++11的新特性来解析C++中的枚举与联合

相关文章

  • 2017-05-28浅谈stringstream 的.str()正确用法和清空操作
  • 2017-05-28Linux下g++编译与使用静态库和动态库的方法
  • 2017-05-28详解C语言中const关键字的用法
  • 2017-05-28华为面试题答案找出最大长度子字符串
  • 2017-05-28c异或运算 c异或运算符号
  • 2017-05-28C/C++中static,const,inline三种关键字详细总结
  • 2017-05-28C语言 位域详解及示例代码
  • 2017-05-28C中的volatile使用方法
  • 2017-05-28C语言实现基于最大堆和最小堆的堆排序算法示例
  • 2017-05-28C++中sprintf()函数的使用详解

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 用C++类实现单向链表的增删查和反转操作方法
    • 算法详解之分支限界法的具体实现
    • 用C# 实现鼠标框选效果的实现代码
    • c++ 巧开平方的实现代码
    • VC创建圆角dialog的实现方法
    • C语言 动态内存分配的详解及实例
    • 位运算实现十进制转换为二进制
    • C语言static修饰函数详细解析
    • 浅谈C语言的字节对齐 #pragma pack(n)2
    • 基于C++ map中key使用指针问题的详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有