【问题标题】:What does "static enum" mean in C++?C++ 中的“静态枚举”是什么意思?
【发布时间】:2011-06-25 16:18:51
【问题描述】:

我最近遇到了这个:

static enum Response{
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};

它在 Microsoft VS2005 下编译和工作。但是,我不确定“静态”修饰符应该做什么。和下面有什么不同吗?

enum Response {
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};

【问题讨论】:

  • 是头文件还是cpp文件?
  • 刚刚在 Visual Studio 2008 中尝试过,它也可以毫无怨言地编译。很奇怪。
  • 在 .cpp 文件中阐明它并且 } 和 ; 之间没有变量名它不是一个变量声明。
  • 详细说明如何在 VS2005、VS2008 和 VS2010 (msdn.microsoft.com/en-us/library/2dzy4k6e.aspx) 中声明 enum 的 msdn 页面没有提及 static。可能是它允许的错误。

标签: c++ visual-studio enums static


【解决方案1】:

仅删除省略号的确切代码不是有效的 C++。您不能在 enum 声明中使用 static 存储类说明符;在那里没有任何意义(只有对象、函数和匿名联合可以声明为static)。

但是,您可以在一个声明中声明一个 enum 和一个变量:

static enum Response {
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
} x; 

这里的static 适用于x,实际上和你说的一样:

enum Response { 
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
};

static Response x;

【讨论】:

  • 我的猜测是,由于这在 C 中是有效的,所以 msvc 在演变成 c++ 编译器时忘记了正确实现这一点
【解决方案2】:

令人惊讶的是,您也可以在其中添加其他 decl-specifiers
这在 VS2008 中编译得很好:

auto const enum TestEnum {
    Why,
    Does
};

register volatile enum TestEnum2 {
    This,
    Work
};

但这根本没有意义:)

我怀疑这里的问题在于解析,因为这样的代码:

enum TestEnum3 { Hello, World };  // Define enum
enum TestEnum3 x = World;         // Use enum

也可以写成:

enum TestEnum3 { Hello, World } x = World; // Define and use enum.

有趣的是,我注意到如果你在 VS2008 中这样做:

enum TestEnum3 { Hello, World };
const enum TestEnum3 e3 = World;
const enum TestEnum4 { F, M, L } e4 = F;

e3 = Hello; // error C2166: l-value specifies const object (Good!)
e4 = M;     // NO ERROR here though - why?

所以它们不等同于TestEnum4 的情况,它似乎抛弃了const decl-specifier。都很奇怪。

【讨论】:

  • 据此看来,他们在解析器中确实存在错误。感谢这个带有“auto const”的示例。
【解决方案3】:
static enum Response { /*... */ };

您不能在 C++ 中定义 static 枚举。 static 只能是枚举的变量,不能是类型本身!

GCC版本4.3.4编译你的代码,它给出了这个错误:

prog.cpp:7: 错误:一个存储类可以 仅针对对象和 功能

在 ideone 在线查看自己:http://www.ideone.com/cI1bt

我想这说明了一切。

--

但是,如果您想将 type enum Response 限制在它自己的翻译单元中,那么您可以使用未命名的命名空间。看看这个话题:

Superiority of unnamed namespace over static?

【讨论】:

  • 显然,在这种特殊的 C++ 风格中,可以做到这一点。但是,您对未命名命名空间的评论非常有趣,谢谢!
  • @Marcin:不,你不能那样做。 VS2005 错误地编译它。阅读詹姆斯的回复;他解释了你什么时候可以写static enum,更重要的是它到底意味着什么。它使 variable 成为静态的,而不是 type 本身。
【解决方案4】:

标准

C++11 N3337 standard draft Annex C 7.1.1 说它在 C 中是允许的,但没有效果,在 C++ 中是非法的:

更改:在 C++ 中,static 或 extern 说明符只能应用于对象或函数的名称。 在 C++ 中将这些说明符与类型声明一起使用是非法的。在 C 中,这些说明符在使用时会被忽略 关于类型声明。示例:

static struct S {    // valid C, invalid in C++
  int i;
};

基本原理:存储类说明符在与类型关联时没有任何意义。在 C++ 中,类 可以使用静态存储类说明符声明成员。允许在类型上使用存储类说明符 声明可能会使用户混淆代码。

struct一样,enum也是一个类型声明。

实施原理

枚举定义没有存储空间,也不会在目标文件中生成符号,如变量和函数。只需尝试编译和反编译:

struct S { int i; int j; };
int i;

与:

g++ -c main.c
nm main.o

您会看到没有S 符号,但有一个i 符号。

当编译器看到一个枚举值时,它只是将它按字面意思插入到编译后的代码中。这当然只有效,因为它们是编译时常量。

因此它们必须包含在头文件中。

另见:

【讨论】:

    【解决方案5】:

    在 C# 中:

    ';'对于 enum 块之后的向后兼容性是可选的。它确实不允许在该语言中为命名类型使用这种语义。 static、public等有特殊考虑。命名空间不能包含字段或方法等成员。

    需要标签:

    ArgTypes var = ArgTypes.CUT;
    

    在 C/C++ 中:

    需要';'在枚举块的末尾。 对于全局命名空间变量、枚举等。默认为 static

    int type;
    
    typedef enum {
      TOKENIZE,
      CUT
    } ArgTypes;
    type = TOKENIZE;  /* <ArgTypes>::TOKENIZE */
    type = ArgTypes::CUT;
    
    // Recommended Use
    enum ArgTypes {
      TOKENIZE,
      CUT
    };  /* Same as above */
    
    enum Test {
      TOKENIZE,
      CUT
    } ArgTypes;
    type = ArgTypes::TOKENIZE;
    type = CUT;   /* Assign type =>  <Test>.CUT */
    type = Test::CUT;
    
    enum {
      TOKENIZE,
      CUT
    } ArgTypes;  /* Unamed.. requires tag */
    type = TOKENIZE; /* <unamed>.TOKENIZE=0 => #define TOKENIZE 0*/
    type = ArgTypes::TOKENIZE;  /* ** ERROR ** */
    

    【讨论】:

      【解决方案6】:

      我不确定为什么使用 static 或者为什么它甚至可以编译。应该只是枚举响应。 枚举器不是静态数据。

      【讨论】:

        猜你喜欢
        • 2013-07-27
        • 2017-01-27
        • 1970-01-01
        • 2010-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-18
        • 2011-06-02
        相关资源
        最近更新 更多