目录
C++核心准则Enum.2: 使用枚举表现一组相关的命名常量
C++核心准则Enum.4:为枚举类型定义运算符以便安全又简单地使用
C++核心准则Enum.7: 只在必要时定义枚举的底层类型(在前置声明枚举时需要定义枚举的底层类型)
C++核心准则Enum.1: 枚举类型比宏定义好
Enum.1: Prefer enumerations over macros
Enum.1: 枚举类型比宏定义好
Reason(原因):
Macros do not obey scope and type rules. Also, macro names are removed during preprocessing and so usually don't appear in tools like debuggers.
宏定义不需要遵守范围和类型规则。同时,宏定义名称会在预编译极端被替换因此通常也不会出现在调试器等工具中。
Example(示例)
First some bad old code:
首先是一些不好的老式代码:
// webcolors.h (third party header)
#define RED 0xFF0000
#define GREEN 0x00FF00
#define BLUE 0x0000FF
// productinfo.h
// The following define product subtypes based on color
#define RED 0
#define PURPLE 1
#define BLUE 2
int webby = BLUE; // webby == 2; probably not what was desired
Instead use an enum:
使用枚举替代:
enum class Web_color { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
enum class Product_info { red = 0, purple = 1, blue = 2 };
int webby = blue; // error: be specific
Web_color webby = Web_color::blue;
We used an enum class to avoid name clashes.
我们可以使用枚举类来避免名称冲突。
Enforcement(实施建议):
Flag macros that define integer values.
标记整数类型的宏定义。
C++核心准则Enum.2: 使用枚举表现一组相关的命名常量
Enum.2: Use enumerations to represent sets of related named constants
Enum.2: 使用枚举表现一组相关的命名常量
Reason(原因)
An enumeration shows the enumerators to be related and can be a named type.
枚举类型表示枚举值之间具有相关性,并且可以成为命名类型。
Example(示例)
enum class Web_color { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
Note(注意)
Switching on an enumeration is common and the compiler can warn against unusual patterns of case labels. For example:
启用枚举类型属于常规操作,并且编译器可以对不平常的用法进行警示。例如:
enum class Product_info { red = 0, purple = 1, blue = 2 };
void print(Product_info inf)
{
switch (inf) {
case Product_info::red: cout << "red"; break;
case Product_info::purple: cout << "purple"; break;
}
}
Such off-by-one switch-statements are often the results of an added enumerator and insufficient testing.
这种"只越界一点"的switch语句通常是增加枚举值后没有充分测试的结果。
Enforcement(实施建议)
Flag switch-statements where the cases cover most but not all enumerators of an enumeration.
提示switch语句覆盖大多数枚举值却没有覆盖所有枚举值的情况。
Flag switch-statements where the cases cover a few enumerators of an enumeration, but has no default.
提示swtich语句覆盖了少数枚举值却没有default分支的情况。
C++核心准则Enum.3:枚举类要比普通的枚举类型好
Enum.3: Prefer class enums over "plain" enums
Enum.3:枚举类要比普通的枚举类型好
Reason(原因)
To minimize surprises: traditional enums convert to int too readily.
尽量减少意外性:经典的枚举类型太容易转换为整数了。
Example(示例)
void Print_color(int color);
enum Web_color { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
enum Product_info { red = 0, purple = 1, blue = 2 };
Web_color webby = Web_color::blue;
// Clearly at least one of these calls is buggy.
Print_color(webby);
Print_color(Product_info::blue);
Instead use an enum class:
而使用枚举类的时候:
void Print_color(int color);
enum class Web_color { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
enum class Product_info { red = 0, purple = 1, blue = 2 };
Web_color webby = Web_color::blue;
Print_color(webby); // Error: cannot convert Web_color to int.
Print_color(Product_info::red); // Error: cannot convert Product_info to int.
Enforcement(示例)
(Simple) Warn on any non-class enum definition.
(简单)警告所有枚举类以外的枚举定义。
C++核心准则Enum.4:为枚举类型定义运算符以便安全又简单地使用
Enum.4: Define operations on enumerations for safe and simple use
Enum.4:为枚举类型定义运算符以便安全又简单地使用
Reason(原因)
Convenience of use and avoidance of errors.
方便使用又少犯错。
Example(示例)
enum Day { mon, tue, wed, thu, fri, sat, sun };
Day& operator++(Day& d)
{
return d = (d == Day::sun) ? Day::mon : static_cast<Day>(static_cast<int>(d)+1);
}
Day today = Day::sat;
Day tomorrow = ++today;
The use of a static_cast is not pretty, but
static_cast的用法不太好,但是:
Day& operator++(Day& d)
{
return d = (d == Day::sun) ? Day::mon : Day{++d}; // error
}
is an infinite recursion, and writing it without a cast, using a switch on all cases is long-winded.
是一个特别深的递归,如果不用cast,使用覆盖所有情况的switch语句又会过于繁杂。 //???如何理解
Enforcement(实施建议)
Flag repeated expressions cast back into an enumeration.
标记反复转换,最后变成枚举类型的表达式。
C++核心准则Enum.5: 不要使用全部大写的枚举值
Enum.5: Don't use ALL_CAPS for enumerators
Enum.5: 不要使用全部大写的枚举值
Reason(原因)
Avoid clashes with macros.
避免和宏定义发生冲突。
Example, bad(反面示例)
// webcolors.h (third party header)
#define RED 0xFF0000
#define GREEN 0x00FF00
#define BLUE 0x0000FF
// productinfo.h
// The following define product subtypes based on color
enum class Product_info { RED, PURPLE, BLUE }; // syntax error
Enforcement(实施建议)
Flag ALL_CAPS enumerators.
标记全部大写的枚举值。
C++核心准则Enum.6:避免无名枚举
Enum.6: Avoid unnamed enumerations
Enum.6:避免无名枚举
Reason(原因)
If you can't name an enumeration, the values are not related
如果你无法为枚举命名,说明这些值之间没有关联!!!
Example, bad(反面示例)
enum { red = 0xFF0000, scale = 4, is_signed = 1 };
Such code is not uncommon in code written before there were convenient alternative ways of specifying integer constants.
在定义整形常量的便利的候选方式存在之前,这样的代码并不少见。
Alternative(可选项)
Use constexpr values instead. For example:
使用常量表达式。例如:
constexpr int red = 0xFF0000;
constexpr short scale = 4;
constexpr bool is_signed = true;
Enforcement(实施建议)
Flag unnamed enumerations.
提示无名枚举。
C++核心准则Enum.7: 只在必要时定义枚举的底层类型(在前置声明枚举时需要定义枚举的底层类型)
Enum.7: Specify the underlying type of an enumeration only when necessary
Enum.7: 只在必要时定义枚举的底层类型
Reason(原因)
The default is the easiest to read and write. int is the default integer type. int is compatible with C enums.
默认的类型更容易读写。int是默认的整数类型。int和C语言枚举类型兼容。
Example(示例)
enum class Direction : char { n, s, e, w,
ne, nw, se, sw }; // underlying type saves space
enum class Web_color : int32_t { red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF }; // underlying type is redundant(多余的; 被裁减的)
Note(注意)
Specifying the underlying type is necessary in forward declarations of enumerations:
※ 在前置声明枚举时需要定义枚举的底层类型!!
enum Flags : char;
void f(Flags);
// ....
enum flags : char { /* ... */ };
C++核心准则Enum.8:只在必要时 指定枚举值
Enum.8: Specify enumerator values only when necessary
Enum.8: 只在必要时指定枚举值
Reason(原因)
It's the simplest. It avoids duplicate enumerator values. The default gives a consecutive set of values that is good for switch-statement implementations.
这样最简单。可以避免重复的枚举值。默认的情况会分配一组容易被switch语句使用的连续值。
Example(示例)
enum class Col1 { red, yellow, blue };
enum class Col2 { red = 1, yellow = 2, blue = 2 }; // typo
enum class Month { jan = 1, feb, mar, apr, may, jun,
jul, august, sep, oct, nov, dec }; // starting with 1 is conventional
enum class Base_flag { dec = 1, oct = dec << 1, hex = dec << 2 }; // set of bits
Specifying values is necessary to match conventional values (e.g., Month) and where consecutive values are undesirable (e.g., to get separate bits as in Base_flag).
为了符合日常习惯(例如月)或者不希望连续值(例如用于获取标志变量中的特定标志位)时有必要定义枚举值。
Enforcement(实施建议)
Flag duplicate enumerator values
标记重复的枚举值
Flag explicitly specified all-consecutive enumerator values
标记显式定义所有枚举值为连续值情况。