- Modern C++:Efficient and Scalable Application Development
- Richard Grimes Marius Bancila
- 518字
- 2021-06-10 18:27:51
Using Enumerations
A final way to provide constants is to use an enum variable. In effect, an enum is a group of named constants, which means that you can use an enum as a parameter to a function. For example:
enum suits {clubs, diamonds, hearts, spades};
This defines an enumeration called suits, with named values for the suits in a deck of cards. An enumeration is an integer type and by default the compiler will assume an int, but you can change this by specifying the integer type in the declaration. Since there are just four possible values for card suits, it is a waste of memory to use int (usually 4 bytes) and instead, we can use char (a single byte):
enum suits : char {clubs, diamonds, hearts, spades};
When you use an enumerated value, you can use just the name; however, it is usual to scope it with the name of the enumeration, making the code more readable:
suits card1 = diamonds;
suits card2 = suits::diamonds;
Both forms are allowed, but the latter makes it more explicit that the value is taken from an enumeration. To force developers to specify the scope, you can apply the keyword class:
enum class suits : char {clubs, diamonds, hearts, spades};
With this definition and the preceding code, the line declaring card2 will compile, but the line declaring card1 will not. With a scoped enum, the compiler treats the enumeration as a new type and has no inbuilt conversion from your new type to an integer variable. For example:
suits card = suits::diamonds;
char c = card + 10; // errors C2784 and C2676
The enum type is based on char but when you define the suits variable as being scoped (with class) the second line will not compile. If the enumeration is defined as not being scoped (without class) then there is an inbuilt conversion between the enumerated value and char.
By default, the compiler will give the first enumerator a value of 0 and then increment the value for the subsequent enumerators. Thus suits::diamonds will have a value of 1 because it is the second value in suits. You can assign values yourself:
enum ports {ftp=21, ssh, telnet, smtp=25, http=80};
In this case, ports::ftp has a value of 21, ports::ssh has a value of 22 (21 incremented), ports::telnet is 22, ports::smtp is 25, and ports::http is 80.
Often the point of enumerations is to provide named symbols within your code and their values are unimportant. Does it matter what value is assigned to suits::hearts? The intention is usually to ensure that it is different from the other values. In other cases, the values are important because they are a way to provide values to other functions.
Enumerations are useful in a switch statement (see later) because the named value makes it clearer than using just an integer. You can also use an enumeration as a parameter to a function and hence restrict the values passed via that parameter:
void stack(suits card)
{
// we know that card is only one of four values
}