本文仅仅讨论如何在SolidMCP中定义更可读的enum,也算是攻克Clean Code和Readable Code的副作用。
-- Piaoger
>> 几种定义enum的方法
其实这几种形式的主要的区别在于:
是否为enum的定义放在一个被嵌套的enum Type内;
enum Type是嵌套在struct还是在namespace之内。
1. 无嵌套
enum DateTimeKind
{
kUnspecified = 0,
kLocalTime = 1,
kUtcTime = 2
};
inline bool isUtc(DateTimeKind kind)
{
return kind == kUtcTime;
}
2. enum Type嵌套在namespace内
namespace DateTimeKind
{
enum Type
{
kUnspecified = 0,
kLocalTime = 1,
kUtcTime = 2
};
}
inline bool isUtc(DateTimeKind::Type kind)
{
return kind == DateTimeKind::kUtcTime;
}
3. enum Type嵌套在struct内
struct DateTimeKind
{
enum Type
{
kUnspecified = 0,
kLocalTime = 1,
kUtcTime = 2
};
}
inline bool isUtc(DateTimeKind::Type kind)
{
return kind == DateTimeKind::kUtcTime;
}
4. 类中的enum Type嵌套在struct内
类中是不可以有namespace的,所以enum Type只能放到struct内
class DateTime
{
public:
struct Kind
{
enum Type
{
kUnspecified = 0,
kLocalTime = 1,
kUtcTime = 2
};
};
private:
// Data Members
};
inline bool isUtc(DateTime::Kind::Type kind)
{
return kind == DateTime::Kind::kUtcTime;
}
5.类的无嵌套enum
class DateTime
{
public:
enum Kind
{
kUnspecified = 0,
kLocalTime = 1,
kUtcTime = 2
};
};
inline bool isUtc(DateTime::Kind kind)
{
return kind == DateTime::kUtcTime;
}
>> 嵌套 Or 不嵌套?
相对而言,Piaoger更喜欢嵌套的形式,这样可以减少名字冲突的机会,并且更具有可读性。
可读性上来讲,DateTime::Kind::kUtcTime 肯定大于DateTime::kUtcTime,我们可以很清楚看出kUtcTime是Time Kind.
至于减少名字冲突,你想为一个类中多个enum都加上一个kUnknown的时候,你就会发现问题了,通常也只能像下面加上一些后缀以示区别:
class ClassName
{
public:
enum EnumXX
{
kUnknownXX = 0,
kValue1XX = 1,
kValue2XX = 2
};
enum EnumYY
{
kUnknownYY = 0,
kValue1YY = 1,
kValue2YY = 2
};
};
>> struct Or namespace
namespace的弱点在于它不能继承,而且还不能用在class和struct内。而struct形式,则是可能某些傻傻的编译器会在struct内偷偷生成代码,如默认构造函数。
鉴于这种傻傻的编译器少见,并且namespace的形式难以统一,Piaoger最终还是选择了struct { enum Type{};};这种形式,即上面提到的的第三种与第四种形式。
>> 尽量把常用的enum放在class之外定义
这样也可以避免一些没有必要的include(尽管enum也可以前向声明).
Qt在qnamespace.h中定义了大量的常用enum。(...\src\corelib\global\qnamespace.h)
我则比较喜欢用在每个Module中加一个XXXTypes.h,把一些相关的enum定义和class前向声明和都放到这个文件内。