当我们需要在日志中输出枚举类型的信息时,如果只记录一个数字,查看日志时就需要再去查找这个枚举值的意思,不直观,不方便,我们会希望可以直接输出这个枚举值对应的字符串。比如下面这个枚举 Color,我们该如何将枚举值 Red 转化为字符串 “Red”?
enum Color{ Red, Orange, Yellow, green };
# 运算符
一种最直接的方法是:使用 map 或者 list 之类的容器做一个映射。还有一个更简单的做法,我们可以借助宏 (macro) 的 # 运算符 (Stringification Operator),该运算符在预编译阶段会将宏参数转换为字符串。
#define str(val) #val
int main(int argc, char *argv[])
{
printf("Value %d in the enum Color is %s\n", Red, str(Red));
}
输出:Value 1 in the enum Color is Red
不幸的是,上诉方式只对直接操作枚举值有效,不适用于变量,比如:
Color cc = Red;
如果使用上述办法,我们将得到:Value 0 in the enum Color is cc。那么我们该怎么得到 cc 对应的枚举值字符串?
方法有很多,可以映射,可以使用更复杂的宏(类似 boost::preprocessor)等等,有兴趣可以尝试。这里重点介绍利用 Qt 的元对象系统实现这个功能。
QMetaEnum 类提供了有关枚举的元数据,而 Q_ENUM 宏可以在元对象系统中注册了一个枚举类型的 QMetaEnum,它必须用在具有 Q_OBJECT 或 Q_GADGET 宏的类中的枚举声明之后。
QMetaEnum 类
name() 返回枚举的名称,scope() 返回声明枚举的类作用域。
key() 返回每个枚举项的名称,value() 返回每个枚举项的值,keyCount() 返回枚举项的数量。
isFlag() 表示该枚举是否打算用作标志,若为 true,意味着可以使用 OR 运算符组合各个枚举值。
keyToValue()、valueToKey() 为转换函数,允许枚举项在名称和值之间转换。
keysToValue() 和 valueToKeys() 对 isFlag() 的枚举提供名称和值的转换,键中字符串以“|”分隔。
详见 Qt 文档:QMet