The C++Course provides a general introduction to programming in C++. It is based on A.B. Downey's book, How to Think Like a Computer Scientist. Click here for details.


Enumerated Types

In the previous chapter I talked about mappings between real-world values like rank and suit, and internal representations like integers and strings. Although we created a mapping between ranks and integers, and between suits and integers, I pointed out that the mapping itself does not appear as part of the program.

Actually, C++ provides a feature called and enumerated type that makes it possible to (1) include a mapping as part of the program, and (2) define the set of values that make up the mapping. For example, here is the definition of the enumerated types Suit and Rank:

enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES };

enum Rank { ACE=1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE,
TEN, JACK, QUEEN, KING };

By default, the first value in the enumerated type maps to 0, the second to 1, and so on. Within the Suit type, the value CLUBS is represented by the integer 0, DIAMONDS is represented by 1, etc.

The definition of Rank overrides the default mapping and specifies that ACE should be represented by the integer 1. The other values follow in the usual way.

Once we have defined these types, we can use them anywhere. For example, the instance variables rank and suit are can be declared with type Rank and Suit:

struct Card
{
  Rank rank;
  Suit suit;

  Card (Suit s, Rank r);
};

That the types of the parameters for the constructor have changed, too. Now, to create a card, we can use the values from the enumerated type as arguments:

  Card card (DIAMONDS, JACK);

By convention, the values in enumerated types have names with all capital letters. This code is much clearer than the alternative using integers:

  Card card (1, 11);

Because we know that the values in the enumerated types are represented as integers, we can use them as indices for a vector. Therefore the old print function will work without modification. We have to make some changes in buildDeck, though:

  int index = 0;
  for (Suit suit = CLUBS; suit <= SPADES; suit = Suit(suit+1)) {
    for (Rank rank = ACE; rank <= KING; rank = Rank(rank+1)) {
      deck[index].suit = suit;
      deck[index].rank = rank;
      index++;
    }
  }

In some ways, using enumerated types makes this code more readable, but there is one complication. Strictly speaking, we are not allowed to do arithmetic with enumerated types, so suit++ is not legal. On the other hand, in the expression suit+1, C++ automatically converts the enumerated type to integer. Then we can take the result and typecast it back to the enumerated type:

  suit = Suit(suit+1);
  rank = Rank(rank+1);

Actually, there is a better way to do this---we can define the ++ operator for enumerated types---but that is beyond the scope of this book.


Last Update: 2005-12-05