wap 网站 手机,网站建设培训ppt,wordpress页面内容,空包网站做红章底单说明#xff1a;C11 关于新枚举的引入#xff0c;主要有以下几个方面#xff1a;
强类型枚举#xff08;enum class#xff09;#xff1a;这是一种新的枚举类型#xff0c;它提供了更强的类型检查。枚举类成员的底层类型#xff1a;在枚举类中#xff0c;可以明确指…说明C11 关于新枚举的引入主要有以下几个方面
强类型枚举enum class这是一种新的枚举类型它提供了更强的类型检查。枚举类成员的底层类型在枚举类中可以明确指定枚举成员的底层整数类型。自动枚举值这个特性允许枚举成员自动从 0 开始赋值并且依次递增。枚举类型的字面量枚举类型可以作为编译时常量使用这使得枚举值可以在模板元编程和编译时决策中发挥作用。枚举类型的范围基于 std::underlying_type通过 std::underlying_type可以获取枚举类型的底层整数类型。枚举类型的比较操作枚举类型的值可以与其他枚举值或布尔值进行比较。
接下来先了解为什么要引入这6个新特性
1 C11中为什么引入以上6个枚举的新特性
C11 引入枚举的新特性主要是为了提高代码的安全性、清晰性、易用性和性能。以下是针对前面提到的六条规则分别引入新特性的原因
强类型枚举enum class引入强类型枚举的主要原因是为了提高类型安全性。在 C11 之前枚举类型enum的成员可以隐式转换为整型这可能导致意外的类型转换错误和难以追踪的 bug。通过引入 enum classC11 强制要求显式转换从而避免了这些类型安全问题。枚举类成员的底层类型指定枚举类成员的底层类型可以让开发者有更多的控制权使得枚举类型的设计更加灵活。这样的设计允许开发者根据需要选择最合适的整数类型例如 uint8_t、int32_t 等以存储枚举成员从而优化内存使用和性能。自动枚举值自动为枚举成员赋值的功能简化了枚举类型的声明减少了代码的冗余。开发者不再需要手动为每个枚举成员指定数值这不仅减少了编码工作量也降低了出错的可能性。枚举类型的字面量允许枚举类型作为字面量使用提高了代码的表达能力和可读性。这使得枚举类型可以更方便地在模板元编程和其他编译时计算中使用同时也使得代码更加简洁和易于理解。枚举类型的范围基于 std::underlying_type通过提供 std::underlying_type 模板C11 使得对枚举类型的值进行迭代和比较变得更加容易。这为枚举类型的操作提供了更多的灵活性同时也使得与枚举类型相关的算法和逻辑更加直观和一致。枚举类型的比较操作提供对枚举类型的比较操作的支持使得枚举类型的值可以与 bool 类型或其他枚举类型的值进行比较。这样的设计提高了枚举类型的实用性使得它们可以更方便地用于条件语句、循环和其他控制结构中同时也使得代码更加清晰和易于维护。
总的来说C11 中枚举类型的这些新特性都是为了提高代码的质量和可维护性同时也使得枚举类型更加强大和易于使用。这些改进反映了 C 社区对于编写更安全、更高效和更易于理解的代码的持续追求。
2 枚举6大新特性使用详解
接下来C11 标准对枚举类型enum进行的6项扩展详细解读如下。
2.1 强类型枚举enum
C11 引入了强类型枚举也称为枚举类enum class它提供了更好的类型安全性。与传统的枚举类型相比枚举类的成员是强类型的不能隐式转换为其他类型这有助于避免意外的类型转换错误。参考代码如下
enum class Color {Red, Green, Blue
};
// Color color 1; // 错误不能隐式转换为Color类型
Color color Color::Red; // 正确使用枚举类成员2.2 枚举类成员的底层类型
2.2 枚举类成员的底层类型
在C11中枚举类enum class允许开发者为枚举成员指定一个底层类型这提供了更多的灵活性和精确性。以下是一些使用枚举类底层类型的案例。
2.2.1 使用 uint8_t 作为底层类型
参考代码如下
enum class TrafficLight : uint8_t {Red 1,Yellow,Green
};TrafficLight light TrafficLight::Green;
在这个例子中TrafficLight 枚举类的底层类型是 uint8_t这意味着枚举成员将使用一个字节的无符号整数来存储。这适用于那些只需要少量值的枚举例如交通信号灯状态。
2.2.2 使用 int16_t 作为底层类型
参考代码如下
enum class TemperatureScale : int16_t {Celsius,Fahrenheit,Kelvin
};TemperatureScale scale TemperatureScale::Celsius;
这里TemperatureScale 枚举类的底层类型是 int16_t它是一个16位的有符号整数。这个选择可能是因为温度尺度的值不需要太大的数值范围但需要有符号整数来表示正负温度。
2.2.3 使用 uint32_t 作为底层类型表示颜色
参考代码如下
enum class Color : uint32_t {Red 0xFF0000,Green 0x00FF00,Blue 0x0000FF
};Color primaryColor Color::Red;
在这个例子中Color 枚举类使用 uint32_t 作为底层类型来表示颜色。每种颜色都有一个对应的RGB值这些值通常用32位无符号整数表示。
2.2.4 使用 int8_t 作为底层类型表示方向
参考代码如下
enum class Direction : int8_t {Up -1,Down,Left,Right
};
Direction moveDirection Direction::Up;这里Direction 枚举类的底层类型是 int8_t它是一个8位的有符号整数。这个选择适用于表示有限数量的方向其中负值和正值可以用来表示相反的方向。
2.2.5 使用 uint64_t 作为底层类型表示大数值枚举
参考代码如下
enum class LargeValue : uint64_t {Value1 10000000000000000ULL,Value2,Value3
};LargeValue value LargeValue::Value1;
在这个例子中LargeValue 枚举类的底层类型是 uint64_t它是一个64位的无符号整数。这个选择适用于需要表示非常大数值的枚举例如在处理大量数据或高性能计算时。
通过为枚举类指定底层类型开发者可以根据枚举的实际用途和所需的数值范围来优化存储和性能。这些案例展示了如何根据不同的应用场景选择合适的底层类型。
2.3 自动枚举值
C11 允许枚举类型的成员自动从 0 开始赋值并依次递增。这简化了枚举值的定义特别是当枚举成员数量较多时。参考代码如下
enum class Direction {Up 0,Right,Down,Left
};
// Direction::Up 的值为 0Direction::Right 的值为 1依此类推
2.4 枚举类型的字面量
枚举类型的字面量是 C11 引入的一项特性它允许枚举类型的成员作为编译时常量使用。这意味着枚举成员可以在模板元编程、常量表达式和需要编译时已知值的场景中使用。以下是几个使用枚举类型字面量的案例
2.4.1 模板函数根据枚举类型处理不同的操作
参考代码如下
template typename T
void process(T t) {// 通用处理
}template
void processLogLevel(LogLevel level) {switch (level) {case LogLevel::Info: // 使用枚举字面量作为模板参数std::cout Information: ;break;case LogLevel::Warning:std::cout Warning: ;break;case LogLevel::Error:std::cout Error: ;break;}// 处理日志信息
}enum class LogLevel {Info,Warning,Error
};processLogLevel::Info(LogLevel::Info); // 调用模板函数
在这个例子中LogLevel 是一个枚举类型它的成员可以用作模板函数的参数。这允许函数根据日志级别采取不同的处理方式。
2.4.2 使用枚举字面量作为数组索引
参考代码如下
enum class Direction {Up,Down,Left,Right
};const char* directionNames[] {[Direction::Up] Up,[Direction::Down] Down,[Direction::Left] Left,[Direction::Right] Right
};std::string name directionNames[Direction::Right]; // 获取 Right
在这个例子中枚举类型的成员作为数组索引使用这使得数组的初始化更加直观和易于维护。
2.4.3 在编译时根据枚举值进行条件编译
参考代码如下
#if defined(_DEBUG)
const int debugLevel 1; // 调试模式下设置调试级别
#else
const int debugLevel 0; // 非调试模式下关闭调试输出
#endifenum class DebugLevel {None 0,Basic 1,Detailed 2
};void logMessage(DebugLevel level) {#if debugLevel DebugLevel::Basicstd::cout Log message: ;#endif// 打印日志消息
}
在这个例子中枚举类型的值用于条件编译这允许在不同的编译配置下控制代码的编译。
2.4.4 使用枚举字面量作为模板元编程的一部分
参考代码如下
enum class LogLevel {None 0,Info,Warning,Error,Fatal
};// 基本的 Logger 模板结构体
template LogLevel L
struct Logger {static void log(const std::string message) {// 默认实现根据日志级别输出不同的前缀std::cout [ toString(L) ] message std::endl;}private:// 将 LogLevel 转换为字符串static std::string toString(LogLevel level) {switch (level) {case LogLevel::None: return None;case LogLevel::Info: return Info;case LogLevel::Warning: return Warning;case LogLevel::Error: return Error;case LogLevel::Fatal: return Fatal;default: return Unknown;}}
};// 特化 LoggerLogLevel::Info 以输出额外信息
template
struct LoggerLogLevel::Info {static void log(const std::string message) {std::cout [ toString(LogLevel::Info) ] [User ID: 12345] message std::endl;}
};// 特化 LoggerLogLevel::Fatal 以立即退出程序
template
struct LoggerLogLevel::Fatal {static void log(const std::string message) {std::cout [FATAL] message std::endl;std::terminate();}
};int main() {//特化输出LoggerLogLevel::Info::log(This is an informational message.);//正常输出LoggerLogLevel::Warning::log(This is a warning message.);//特化输出LoggerLogLevel::Fatal::log(This is a fatal error message.);return 0;
}
在上面的代码中我们定义了一个 Logger 模板结构体它有一个 log 静态成员函数用于输出日志消息。我们还提供了两个特化版本一个为 LogLevel::Info它会输出一个额外的用户 ID另一个为 LogLevel::Fatal它会在输出日志后立即退出程序。
这个案例展示了如何使用枚举字面量作为模板元编程的一部分允许我们根据不同的枚举值来特化模板函数或类。这种方法提供了极大的灵活性使得我们可以根据枚举的不同值来定制不同的行为。
通过以上这些案例我们可以看到枚举类型字面量在模板编程、条件编译和编译时常量计算中的灵活性和实用性。这些特性使得枚举类型成为 C11 中更加强大和有用的工具。
2.5 关于std::underlying_type
C11 提供了 std::underlying_type 模板它可以获取枚举类型的底层整数类型。这使得对枚举类型的值进行迭代和比较变得更加容易。参考代码如下
enum class Direction : int8_t{Up 0,Down,Left,Right
};Direction d Direction::Up;
for (auto i static_caststd::underlying_typeDirection::type(0); i static_caststd::underlying_typeDirection::type(d) 1; i) {// 遍历 Direction 的所有值
}
例子中std::underlying_typeDirection::type 实际上就是int8_tstd::underlying_type 提供了枚举的底层整数类型而 static_cast 用于在已知两个类型之间存在合法转换的情况下进行类型转换。它们经常一起使用以便在枚举类型和其底层整数类型之间进行安全的转换。
2.6 枚举类型的比较操作
C11 标准库提供了对枚举类型的比较操作的支持使得枚举类型的值可以与bool类型或其他枚举类型的值进行比较。这提高了枚举类型的表达能力和易用性。参考代码如下
#include iostream// 定义一个表示状态的枚举类型
enum class Status {Active,Inactive,Pending
};// 函数根据状态打印出不同的信息
void printStatusMessage(Status status) {if (status Status::Active) {std::cout The status is active. std::endl;} else if (status Status::Inactive) {std::cout The status is inactive. std::endl;} else if (status Status::Pending) {std::cout The status is pending. std::endl;} else {std::cout Unknown status. std::endl;}
}// 检查状态是否为非活动状态并打印相应的信息
void checkIfInactive(Status status) {// 直接将枚举值与 bool 类型进行比较if (!status) {std::cout The status is not active. std::endl;}
}int main() {Status currentStatus Status::Inactive;// 打印状态信息printStatusMessage(currentStatus);// 检查状态是否为非活动状态checkIfInactive(currentStatus);return 0;
}
在 checkIfInactive 函数中我们使用了 ! 逻辑非运算符来检查 Status 枚举值是否为 Inactive 或 Pending这两个状态可以被视为非活动状态。由于 Inactive 和 Pending 在枚举中是第一个和第二个值它们在 C 中默认对应于 false值为 0和 true值为 1。因此当我们使用 !status 进行比较时如果 status 是 Active值为 2 或更高条件将评估为 true并打印出 The status is not active. 信息。
这个例子展示了如何直接将枚举类型的值与 bool 类型进行比较利用了枚举值在 C 中的隐式转换为整数的特性。这种比较操作在处理状态标志或需要根据枚举值的真假状态做出决策时非常有用。