当前位置: 首页 > wzjs >正文

企业网站建设案例分析手机版网站开发html5

企业网站建设案例分析,手机版网站开发html5,哪个网站做的系统好,昌平做网站条款10:优先使用作用域限制的enmus而不是无作用域的enum 一般而言,在花括号里面声明的变量名会限制在括号外的可见性。但是这对于C98风格的enums中的枚举元素并不成立。枚举元素和包含它的枚举类型同属一个作用域空间,这意味着在这个作用域中…

条款10:优先使用作用域限制的enmus而不是无作用域的enum

一般而言,在花括号里面声明的变量名会限制在括号外的可见性。但是这对于C++98风格的enums中的枚举元素并不成立。枚举元素和包含它的枚举类型同属一个作用域空间,这意味着在这个作用域中不能再有同样名字的定义:

	enum Color { black, white, red};                 // black, white, red 和// Color  同属一个定义域auto white = false;                              // 错误!因为 white// 在这个定义域已经被声明过

事实就是枚举元素泄露到包含它的枚举类型所在的作用域中,对于这种类型的enum官方称作无作用域的(unscoped)。在C++11中对应的使用作用域的enums(scoped enums)不会造成这种泄露:

	enum class Color { black, white, red};            // black, white, red// 作用域为 Colorauto white = false;                               // fine, 在这个作用域内// 没有其他的 "white"Color c = white;                                  // 错误!在这个定义域中// 没有叫"white"的枚举元素Color c = Color::white;                           // fineauto c = Color::white;                            // 同样没有问题(和条款5// 的建议项吻合)

因为限制作用域的enum是通过"enum class"来声明的,它们有时被称作枚举类(enum class)。

限制作用域的enum可以减少命名空间的污染,这足以是我们更偏爱它们而不是不带限制作用域的表亲们。除此之外,限制作用域的enums还有一个令人不可抗拒的优势:它们的枚举元素可以是更丰富的类型。无作用域的enum会将枚举元素隐式的转换为整数类型(从整数出发,还可以转换为浮点类型)。因此像下面这种语义上荒诞的情况是完全合法的:

	enum Color { black, white, red };                  // 无限制作用域的enumstd::vector<std::size_t>                           // 返回x的质因子的函数primeFactors(std::size_t x);Color c = red;...if (c < 14.5 ){                                   // 将Color和double类型比较!auto  factors =                               // 计算一个Color变量的质因子primeFactors(c); }

"enum"后增加一个"class",就可以将一个无作用域的enum转换为一个有作用域的enum,变成一个有作用域的enum之后,事情就变得不一样了。在有作用域的enum中不存在从枚举元素到其他类型的隐式转换:

	enum class Color { black, white, red };           // 有作用域的enumColor c = Color::red;                             // 和前面一样,但是...                                               // 加上一个作用域限定符if (c < 14.5){                                    // 出错!不能将Color类型// 和double类型比较auto factors =                                  // 出错!不能将Color类型传递给primeFactors(c);                              // 参数类型为std::size_t的函数...}

如果你就是想将Color类型转换为一个其他类型,使用类型强制转换(cast)可以满足你这种变态的需求:

	if(static_cast<double>(c) < 14.5) {              // 怪异但是有效的代码auto factors =                                   // 感觉不可靠primeFactors(static_cast<std::size_t(c));      // 但是可以编译...
}

相较于无定义域的enum,有定义域的enum也许还有第三个优势,因为有定义域的enum可以被提前声明的,即可以不指定枚举元素而进行声明:

	enum Color;                                      // 出错!enum class Color;                                // 没有问题

这是一个误导。在C++11中,没有定义域的enum也有可能被提前声明,但是需要一点额外的工作。这个工作时基于这样的事实:C++中的枚举类型都有一个被编译器决定的潜在的类型。对于一个无定义域的枚举类型像Color,

    enum Color {black, white, red };

编译器有可能选择char作为潜在的类型,因为仅仅有三个值需要表达。然而一些枚举类型有很大的取值的跨度,如下:

	enum Status { good = 0,failed = 1,incomplete = 100,corrupt = 200,indeterminate = 0xFFFFFFFF};

这里需要表达的值范围从00xFFFFFFFF。除非是在一个不寻常的机器上(在这台机器上,char类型至少有32bit),编译器一定会选择一个取值范围比char大的整数类型来表示Status的类型。

为了更高效的利用内存,编译器通常想为枚举类型选择可以充分表示枚举元素的取值范围但又占用内存最小的潜在类型。在某些情况下,为了代码速度的优化,可以回牺牲内存大小,在那种情况下,编译器可能不会选择占用内存最小的可允许的潜在类型,但是编译器依然希望能过优化内存存储的大小。为了使这种功能可以实现,C++98仅仅支持枚举类型的定义(所有枚举元素被列出来),而枚举类型的声明是不被允许的。这样可以保证在枚举类型被用到之前,编译器已经给每个枚举类型选择了潜在类型。

不能事先声明枚举类型有几个不足。最引人注意的就是会增加编译依赖性。再次看看Status这个枚举类型:

	enum Status { good = 0,failed = 1,incomplete = 100,corrupt = 200,indeterminate = 0xFFFFFFFF};

这个枚举体可能会在整个系统中都会被使用到,因此被包含在系统每部分都依赖的一个头文件当中。如果一个新的状态需要被引入:

	enum Status { good = 0,failed = 1,incomplete = 100,corrupt = 200,audited = 500,indeterminate = 0xFFFFFFFF};

就算一个子系统——甚至只有一个函数!——用到这个新的枚举元素,有可能导致整个系统的代码需要被重新编译。这种事情是人们憎恨的。在C++11中,这种情况被消除了。例如,这里有一个完美的有效的有作用域的enum的声明,还有一个函数将它作为参数:

	enum class Status;                  // 前置声明void continueProcessing(Status s);  // 使用前置声明的枚举体

如果Status的定义被修改,包含这个声明的头文件不需要重新编译。更进一步,如果Status被修改(即,增加audited枚举元素),但是continueProcessing的行为不受影响(因为continueProcessing没有使用audited),continueProcessing的实现也不需要重新编译。

但是如果编译器需要在枚举体之前知道它的大小,C++11的枚举体怎么做到可以前置声明,而C++98的枚举体无法实现?原因是简单的,对于有作用域的枚举体的潜在类型是已知的,对于没有作用域的枚举体,你可以指定它。

对有作用域的枚举体,默认的潜在的类型是int:

	enum class Status;                  // 潜在类型是int

如果默认的类型不适用于你,你可重载它:

	enum class Status: std::uint32_t;   // Status潜在类型是// std::uint32_t// (来自<cstdint>)

无论哪种形式,编译器都知道有作用域的枚举体中的枚举元素的大小。

为了给没有作用域的枚举体指定潜在类型,你需要做相同的事情,结果可能是前置声明:

	enum Color: std::uint8_t;          // 没有定义域的枚举体// 的前置声明,潜在类型是// std::uint8_t

潜在类型的指定也可以放在枚举体的定义处:

	enum class Status: std::uint32_t{ good = 0,failed = 1,incomplete = 100,corrupt = 200,audited = 500,indeterminate = 0xFFFFFFFF};

从有定义域的枚举体可以避免命名空间污染和不易受无意义的隐式类型转换影响的角度看,你听到至少在一种情形下没有定义域的枚举体是有用的可能会感到惊讶。这种情况发生在引用C++11std::tuples中的某个域时。例如,假设我们有一个元组,元组中保存着姓名,电子邮件地址,和用户在社交网站的影响力数值:

	using UserInfo =                 // 别名,参见条款9std::tuple<std::string,        // 姓名std::string,        // 电子邮件std::size_t> ;      // 影响力

尽管注释已经说明元组的每部分代表什么意思,但是当你遇到像下面这样的源代码时,可能注释没有什么用:

	UserInfo uInfo;                  // 元组类型的一个对象...auto val = std::get<1>(uInfo);   // 得到第一个域的值

作为一个程序员,你有很多事要做。你真的想去记住元组的第一个域对应的是用户的电子邮件地址?我不这么认为。使用一个没有定义域的枚举体来把名字和域的编号联系在一起来避免去死记这些东西:

	enum UserInfoFields {uiName, uiEmail, uiReputation };UserInfo uInfo;                         // 和前面一样...auto val = std::get<uiEmail>(uInfo);    // 得到电子邮件域的值

上面代码正常工作的原因是UserInfoFieldsstd::get()要求的std::size_t的隐式类型转换。

如果使用有作用域的枚举体的代码就显得十分冗余:

	enum class UserInfoFields { uiName, uiEmail, uiReputaion };UserInfo uInfo;                        // 和前面一样...auto val = std::get<static_cast<std::size_t>(UserInfoFields::uiEmail)>(uInfo);

写一个以枚举元素为参数返回对应的std::size_t的类型的值可以减少这种冗余性。std::get是一个模板,你提供的值是一个模板参数(注意用的是尖括号,不是圆括号),因此负责将枚举元素转化为std::size_t的这个函数必须在编译阶段就确定它的结果。就像条款15解释的,这意味着它必须是一个constexpr函数。

实际上,它必须是一个constexpr函数模板,因为它应该对任何类型的枚举体有效。如果我们打算实现这种一般化,我们需要一般化返回值类型。不是返回std::size_t,我们需要返回枚举体的潜在类型。通过std::underlying_type类型转换来实现(关于类型转换的信息,参见条款9)。最后需要将这个函数声明为noexcept(参见条款14),因为我们知道它永远不会触发异常。结果就是这个函数模板可以接受任何的枚举元素,返回这个元素的在编译阶段的常数值:

	template<typename E>constexpr typename std::underlying_type<E>::typetoUType(E enumerator) noexcept{returnstatic_cast<typename std::underlying_type<E>::type>(enumerator);}

C++14中,toUType可以通过将std::underlying_type<E>::type替代为std::underlying_type_t(参见条款9):

	template<typename E>                           // C++14constexpr std::underlying_type_t<E>toUType(E enumerator) noexcept{return static_cast<std::underlying_type_t<E>>(enumerator);}

更加优雅的auto返回值类型(参见条款3)在C++14中也是有效的:

	template<typename E>constexpr autotoUType(E enumerator) noexcept{return static_cast<std::underlying_type_t<E>>(enumerator);}

无论写哪种形式,toUType允许我们想下面一样访问一个元组的某个域:

	auto val = std::get<toUType(UserInfoFields::uiEmail)>(uInfo);

这样依然比使用没有定义域的枚举体要复杂,但是它可以避免命名空间污染和不易引起注意的枚举元素的的类型转换。很多时候,你可能会决定多敲击一些额外的键盘来避免陷入一个上古时代的枚举体的技术陷阱中。

要记住的东西
C++98
风格的enum
是没有作用域的enum
有作用域的枚举体的枚举元素仅仅对枚举体内部可见。只能通过类型转换(cast
)转换为其他类型
有作用域和没有作用域的enum
都支持指定潜在类型。有作用域的enum
的默认潜在类型是int
。没有作用域的enum
没有默认的潜在类型。
有作用域的enum
总是可以前置声明的。没有作用域的enum
只有当指定潜在类型时才可以前置声明。
http://www.dtcms.com/wzjs/589059.html

相关文章:

  • 网站被封怎么江西网站开发公司电话
  • js网站模板免费下载包头网站建设平台广和
  • 长沙企业做网站哪家好电子商务的网站建设的可用性
  • 做网站用广告赚钱过时了网站 会员系统 织梦
  • 公司网站设计费计入什么科目怎么给网站刷流量
  • 河南省城乡和住房建设厅网站首页电商网站产品模块
  • c 网站开发的好处珠海高端网站开发
  • 深圳市网站建设科技公司微信网站开发详解
  • 网站开发方面的岗位怎么做app和网站购物
  • 做网站建设公司赚钱吗长春是几线城市2021
  • 上海网站建设开发公司哪家好江苏元鼎建设工程有限公司网站
  • 免费网站搭建系统制作一个手机app软件
  • discuz网站怎么做排名铁路工程造价信息网
  • 如何更改网站模板wordpress建站 图片
  • 苏州建站公司兴田德润简介呢在线网站推荐几个
  • 河南郑州建设厅网站手机表白网站在线制作
  • 做彩票网站能挣到钱吗网站设计中的js是什么
  • 哪个公司做网站建设好淘宝客免费建网站
  • 河北建设集团有限公司网站网页制作软件哪个好用
  • 网站套用女生化妆品网站建设规划书
  • 网站域名跳转怎么做可以自己设计房子的游戏
  • 个人的网站备案多少钱网站备案人授权
  • 15年做哪些网站致富深圳网站建设 乐云seo
  • 工商局加强网站建设的通知wordpress广告插件下载
  • 邯郸外贸网站建设怎么建设网站网页
  • 全站加速 wordpresshtml全屏网站
  • 上海网站案例电子工程网络信息技术专业
  • 学习html的网站注册安全工程师注册管理系统官网
  • 免费的网站域名查询565wcc贵阳建设公司网站
  • 如何免费建com的网站石家庄本地招聘信息网