12

我目前正在考虑命名空间枚举或命名空间静态常量组是否更可取的问题。什么应该是默认选择,为什么?

选项1:

namespace Direction
{
    enum Direction
    {
        north,
        east,
        south,
        west,
    };
}

选项 2:

namespace Direction
{
    static const unsigned char north = 0;
    static const unsigned char east = 1;
    static const unsigned char south = 2;
    static const unsigned char west = 3;
}

两者都有其优点和缺点。

专业枚举:

  1. 一些类型安全:

    void foo(Direction dir); // the compiler won't allow you to just pass an int or a value of an unrelated enum without explicitly casting it
    

反对枚举:

  1. 类型安全相当有限:

    enum A
    {
        Entry1 = 1
    };
    
    enum B
    {
        Entry2 = 10
    };
    
    A a;
    if(a == Entry2)
        ; // ouch!
    
  2. 不支持除 int 以外的任何其他类型 - 在 C++ 11 之前,不能只拥有例如 long long、short 或 char 的枚举

  3. 枚举的命名空间不是最理想的

    1. 如果不将枚举包装到单独的命名空间中,那么它的所有成员都会污染周围的命名空间。

    2. 如果确实将枚举包装到一个单独的命名空间中,那么在将枚举本身用作一种类型时会得到一些冗余:然后必须以 Direction::Direction 的方式声明一个方向变量(当不执行“使用 Direction:: Direction”,这将让它们再次污染外部命名空间(最后在代码的那部分,using 指令生效的地方)),以便能够以 Direction::north 而不是仅北的方式命名其成员

临静态常量:

  1. 在 C++ 11 之前的 C++ 中更好的类型支持 - 例如,可以使用 unsigned char 等类型作为常量
  2. 适当的范围界定 - 没有外部命名空间的污染,没有通过 using 指令明确要求它(即使这样也只是在有限的范围内)

反静态常量:

  1. 甚至比枚举更不安全——不能再像这样声明函数原型:

    void foo(Direction dir);
    

    但必须通过以下方式进行:

    void foo(unsigned char dir); // now each variable of type unsigned char or of a type that can implicitly be casted into unsigned char can be passed, even if its totally unrelated to the expected "enumeration" or if the value does not match the value of any of the expected consts
    

编辑: 在这里我发现了一篇关于枚举类型安全限制的有趣文章: http ://www.drdobbs.com/enumerations/184401797

4

3 回答 3

2

最大的区别是打字。枚举具有不同的类型;static const 必须具有现有的整数类型(尽管它可以在其他地方使用)。哪个更可取取决于您想要什么:在 的情况下Direction,您可能想要一个唯一的类型,而枚举更可取。在其他情况下,您真正​​想要的是具有整数类型的命名常量,例如数组的维度。在这些情况下,静态 const 可能更可取。

于 2013-11-08T18:20:19.080 回答
1

使用枚举,您可以将属于一个概念的所有常量联系在一起(使用名为 的唯一 c++ 标识符enum)。

Herb Sutter 写过更喜欢新风格的演员表 ( static_cast) 而不是 C 演员表。他的一个论点(除其他外)是可以在源代码中使用正则表达式找到它们。

回到您的问题,这意味着如果您enum可以通过代码库 grep 来查找要一起使用的常量的出现。这对于命名空间中的常量是不可能的。

于 2013-11-08T18:58:31.643 回答
1

C++11通过强类型枚举和改进的作用域解决了所有的矛盾点。

对于一组固定值,例如您的基本方向示例,我会使用枚举。

于 2013-11-08T18:21:25.920 回答