Enumeration type in C inherits in C language. Just like other characteristics from C language inherited, C enumerations also have a disadvantage, which is the most significant thing that is the role domain problem - constant defined in the enumeration type, which belongs to the scope of definition enumeration, not It belongs to this enumeration type. For example, the following example:
ENUM FileAccess {read = 0x1, Write = 0x2,};
FileAccess Access = :: read; // correct fileAccess access = fileaccess :: read; // error
This feature of C enumeration is unacceptable for people who are used to object-oriented and scope concepts. First, FileAccess :: read is clearly more in line with the programmer's intuition, because the above enumeration defines the following definition (actually, the enumeration type in .NET is so real):
Class FileAccess {static const Int = 0x1; static const Int write = 0x2;
Second, this causes us to define an enumeration value of two equally named names in the same scope. That is, the following code is compilation error:
ENUM FileAccess {read = 0x1, Write = 0x2,};
Enum fileshare {read = 0x1, // Redefile WRITE = 0x2, // Refinition};
If this doesn't make you angry, you may haven't worked how much C code :-). In fact, in the latest C 0x standard draft proposal for enumerating the role domain issues, what is the final solution will not be in the prophet, after all, for the use of a wide language like C , any Features' inclusion and modification must be very careful.
Of course, we can use some roundabout way to solve this problem (C can always give us a lot of surprises and accidents). For example, we can put an enumeration value in a structure and use an operator overload to approach the characteristics of enumeration:
Struct FileAccess {ENUM __ENUM {read = 0x1, Write = 0x2}; __enum _value; // enumeration value
FileAccess (int value = 0): _Value ((__ enum) value) {} fileaccess & operator = (int value) {this -> _ value = (__enum) value; return * this;} Operator int () const {return this-> _Value;}};
We can now use this enumeration type in the hope:
FileAccess Access = FileAccess :: read;
And because we provide a conversion operator to the int type, it can be used in places where Int is required, such as the Switch statement:
Switch (Access) {Case FileAccess :: Read: Break; Case FileAccess :: Write: Break;
Of course, we don't want to write such a structure each time. By using the macro, we can easily do this: #define declare_enum (e) / struct e / {/ public: / e (int value = 0): _Value ((__ enum) {/} / e & operator = (int value) {/ this -> _ value = (__enum) value; / return * this; /} / operator int () const {/ return this -> _ value; /} // enum __enum {
#define end_enum () /}; // private: / __enum _value; /};
We can now define the previous enumerations as follows and is not complicated than directly write ENUM.
Declare_enum (FileAccess) Read = 0x1, Write = 0x2, End_enum ()
Declare_enum (fileshare) read = 0x1, Write = 0x2, End_enum ()