The enumeration type in C ++ inherits from the C language. Just like many other features inherited from the C language, the C ++ enumeration also has disadvantages. The most significant one is the scope problem-a constant defined in the enumeration type, it belongs to the scope of the defined enumeration, and does not belong to this enumeration type. For example:
Enum fileaccess {
Read = 0x1,
Write = 0x2,
};
Fileaccess access =: read; // correct
Fileaccess access = fileaccess: read; // Error
This feature of C ++ enumeration is unacceptable for those who are used to object-oriented and scope concepts. First, fileaccess: Read is obviously more consistentProgramMember intuition, because the above enumeration definition should be equivalent to the following definition (in fact, the enumeration type in. NET is implemented in this way ):
Class fileaccess {
Static const int READ = 0x1;
Static const int write = 0x2;
};
Secondly, we cannot define two enumeration values with the same name in the same scope. That is to say, the followingCodeIs a compilation error:
Enum fileaccess {
Read = 0x1,
Write = 0x2,
};
Enum fileshare {
Read = 0x1, // redefinition
Write = 0x2, // redefines
};
If this does not make you angry, you may not have written much C ++ code :-). In fact, in the latest draft C ++ 0x standard, there are proposals on enumeration scope issues, but what the final solution will be, cannot be left blank, after all, you must be cautious when adding, deleting, or modifying any feature in a widely used language like C ++.
Of course, we can use some roundabout methods to solve this problem (C ++ can always surprise and surprise us a lot ). For example, we can place enumeration values in a structure and use Operator Overloading to approximate enumeration features:
struct fileaccess {
Enum _ Enum {
Read = 0x1,
write = 0x2
};
_ Enum _ value; // enumerated 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 use this enumeration type as expected:
Fileaccess access = fileaccess: read;
Besides, because we provide an int-type conversion operator, we can use it wherever int is needed, such as the switch statement:
Switch (ACCESS ){
Case fileaccess: Read:
Break;
Case fileaccess: write:
Break;
}
Of course, we do not want to write such a structure manually every time. By using macros, we can easily achieve this:
# define declare_enum (e)/
struct E/
{/
Public:/
E (INT value = 0): _ value (_ Enum) value) {/
}/
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 enumeration as follows, and it is no more complicated than writing Enum directly.
Declare_enum (fileaccess)
Read = 0x1,
Write = 0x2,
End_enum ()
declare_enum (fileshare)
Read = 0x1,
write = 0x2,
end_enum ()