C++ Programming

From Wikibooks, open books for an open world
Jump to: navigation, search

The enum keyword is used to create an enumerated type named name that consists of the elements in name-list. The var-list argument is optional, and can be used to create instances of the type along with the declaration.

Syntax
    enum name {name-list} var-list;

For example, the following code creates the desired data type:

enum card_suit {Clubs,Diamonds,Hearts,Spades};
card_suit first_cards_suit=Diamonds;
card_suit second_cards_suit=Hearts;
card_suit third_cards_suit=0; //Would cause an error, 0 is an "integer" not a "card_suit" 
card_suit forth_cards_suit=first_cards_suit; //OK, they both have the same type.

The line of code creates a new data type "card_suit" that may take on only one of four possible values: "Clubs", "Diamonds", "Hearts", and "Spades". In general the enum command takes the form:

enum new_type_name { possible_value_1,
                     possible_value_1,
                     /* ..., */
                     possible_value_n
} Optional_Variable_With_This_Type;

While the second line of code creates a new variable with this data type and initializes it to value to Diamonds". The other lines create new variables of this new type and show some initializations that are (and are not) possible.

Internally enumerated types are stored as integers, that begin with 0 and increment by 1 for each new possible value for the data type.

enum apples { Fuji, Macintosh, GrannySmith };
enum oranges { Blood, Navel, Persian };
apples pie_filling = Navel; //error can't make an apple pie with oranges.
apples my_fav_apple = Macintosh;
oranges my_fav_orange = Navel; //This has the same internal integer value as my_favorite_apple
 
//Many compilers will produce an error or warning letting you know your comparing two different quantities.
if(my_fav_apple == my_fav_orange) 
  std::cout << "You shouldn't compare apples and oranges" << std::endl;

While enumerated types are not integers, they are in some case converted into integers. For example, when we try to send an enumerated type to standard output.

For example:

enum color {Red, Green, Blue};
color hair=Red;
color eyes=Blue;
color skin=Green;
std::cout << "My hair color is " << hair << std::endl;
std::cout << "My eye color is " << eyes << std::endl;
std::cout << "My skin color is " << skin << std::endl;
if (skin==Green)
  std::cout << "I am seasick!" << std::endl;

Will produce the output:

My hair color is 0
My eye color is 2
My skin color is 1
I am seasick!

We could improve this example by introducing an array that holds the names of our enumerated type such as:

std::string color_names[3]={"Red", "Green", "Blue"};
enum color {Red, Green, Blue};
color hair=Red;
color eyes=Blue;
color skin=Green;
std::cout << "My hair color is " << color_names[hair] << std::endl;
std::cout << "My eye color is " << color_names[eyes] << std::endl;
std::cout << "My skin color is " << color_names[skin] << std::endl;

In this case hair is automatically converted to an integer when it is index arrays. This technique is intimately tied to the fact that the color Red is internally stored as "0", Green is internally stored as "1", and Blue is internally stored as "2". Be Careful! One may override these default choices for the internal values of the enumerated types.

This is done by simply setting the value in the enum such as:

enum color {Red=2, Green=4, Blue=6};

In fact it is not necessary to an integer for every value of an enumerated type. In the case the value, the compiler will simply increase the value of the previous possible value by one.

Consider the following example:

enum colour {Red=2, Green, Blue=6, Orange};

Here the internal value of "Red" is 2, "Green" is 3, "Blue" is 6 and "Orange is 7. Be careful to keep in mind when using this that the internal values do not need to be unique.

Enumerated types are also automatically converted into integers in arithmetic expressions. Which makes it useful to be able to choose particular integers for the internal representations of an enumerated type.

One may have enumerated for the width and height of a standard computer screen. This may allow a program to do meaningful calculations, while still maintaining the benefits of an enumerated type.

enum screen_width {SMALL=800, MEDIUM=1280};
enum screen_height {SMALL=600, MEDIUM=768};
screen_width MyScreenW=SMALL;
screen_height MyScreenH=SMALL;
std::cout << "The number of pixels on my screen is " << MyScreenW*MyScreenH << std::endl;

It should be noted that the internal values used in an enumerated type are constant, and cannot be changed during the execution of the program.

It is perhaps useful to notice that while the enumerated types can be converted to integers for the purpose arithmetic, they cannot be iterated through.

For example:

enum month { JANUARY=1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER};
 
for( month cur_month = JANUARY; cur_month <= DECEMBER; cur_month=cur_month+1)
{
  std::cout << cur_month << std::endl;
}

This will fail to compile. The problem is with the for loop. The first two statements in the loop are fine. We may certainly create a new month variable and initialize it. We may also compare two months, where they will be compared as integers. We may not increment the cur_month variable. "cur_month+1" evaluates to an integer which may not be stored into a "month" data type.

In the code above we might try to fix this by replacing the for loop with:

for( int monthcount = JANUARY; monthcount <= DECEMBER; monthcount++)
{
  std::cout << monthcount  << std::endl;
}

This will work because we can increment the integer "mounthcount".