可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I recently came across this:
static enum Response{
NO_ERROR=0,
MISSING_DESCRIPTOR,
...
};
It compiles and works under Microsoft VS2005. However, I'm not sure what the 'static' modifier is supposed to do. Is it any different from the following?
enum Response {
NO_ERROR=0,
MISSING_DESCRIPTOR,
...
};
回答1:
That exact code, with just the ellipsis removed, is not valid C++. You can't use the static
storage class specifier in an enum
declaration; it doesn't make any sense there (only objects, functions, and anonymous unions can be declared static
).
You can, however, declare an enum
and a variable all in one declaration:
static enum Response {
NO_ERROR = 0,
MISSING_DESCRIPTOR
} x;
The static
here applies to x
and it is effectively the same as if you said:
enum Response {
NO_ERROR = 0,
MISSING_DESCRIPTOR
};
static Response x;
回答2:
Surprisingly you can put other decl-specifiers in there too.
This compiles fine in VS2008:
auto const enum TestEnum {
Why,
Does
};
register volatile enum TestEnum2 {
This,
Work
};
But it makes no sense at all :)
I suspect the problem here is in the parsing, because code like this:
enum TestEnum3 { Hello, World }; // Define enum
enum TestEnum3 x = World; // Use enum
Could also be written as:
enum TestEnum3 { Hello, World } x = World; // Define and use enum.
Interestingly, I notice if you do this in 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?
So they are not equivalent as in the TestEnum4
case it seems to be throwing away the const
decl-specifier. All very odd.
回答3:
static enum Response { /*... */ };
You cannot define static
enum in C++. static
can only be the variable of the enum, not the type itself!
Compiling your code with GCC
version 4.3.4
, it gives this error:
prog.cpp:7: error: a storage class can
only be specified for objects and
functions
See yourself online at ideone: http://www.ideone.com/cI1bt
I think that says it all.
--
However, if you want to limit the type enum Response
in it's own translation unit, then you can use unnamed namespace. Have a look at this topic:
Superiority of unnamed namespace over static?
回答4:
Standard
The C++11 N3337 standard draft Annex C 7.1.1 says that it was allowed in C but had no effect, and became illegal in C++:
Change: In C ++, the static or extern specifiers can only be applied to names of objects or functions.
Using these specifiers with type declarations is illegal in C ++. In C, these specifiers are ignored when used
on type declarations. Example:
static struct S { // valid C, invalid in C++
int i;
};
Rationale: Storage class specifiers don’t have any meaning when associated with a type. In C ++, class
members can be declared with the static storage class specifier. Allowing storage class specifiers on type
declarations could render the code confusing for users.
And like struct
, enum
is also a type declaration.
Implementation rationale
Enum definitions have no storage, and do no generate symbols in object files like variables and functions. Just try compiling and decompiling:
struct S { int i; int j; };
int i;
with:
g++ -c main.c
nm main.o
and you will see that there is no S
symbol, but there is an i
symbol.
When the compiler sees an enum values, it just inserts it literally into the compiled code. This only works of course because they are compile-time constants.
They must therefore be included on header files.
See also:
- related question for
static struct
in C: Why and when to use static structures in C programming?
回答5:
In C#:
The ';' is optional for backwards compatibility after the enum block. It does not allow for such semantics in that language for named types. static, public, etc. have special consideration. Namespace cannot contain members such as fields or methods.
Requires tag:
ArgTypes var = ArgTypes.CUT;
In C/C++:
Requires ';' at the end of enum block.
For global namespace variables, enumerations, etc. static is by default.
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:
Im not sure why static was used or why it even compiles. Should just be enum Response.
Enumerators are not static data.