Selecting

If you want to test to see if a variable is one of several values, using multiple if statements becomes cumbersome. The C++ switch statement fulfills this purpose much better. The basic syntax is shown here:

    int i; 
std::cin >> i;
switch(i)
{
case 1:
std::cout << "one" << std::endl;
break;
case 2:
std::cout << "two" << std::endl;
break;
default:
std::cout << "other" << std::endl;
}

Each case is essentially a label as to the specific code to be run if the selected variable is the specified value. The default clause is for values where there exists no case. You do not have to have a default clause, which means that you are testing only for specified cases. The default clause could be for the most common case (in which case, the cases filter out the less likely values) or it could be for exceptional values (in which case, the cases handle the most likely values).

A switch statement can only test integer types (which includes enum), and you can only test for constants. The char type is an integer, and this means that you can use characters in the case items, but only individual characters; you cannot use strings:

    char c; 
std::cin >> c;
switch(c)
{
case 'a':
std::cout << "character a" << std::endl;
break;
case 'z':
std::cout << "character z" << std::endl;
break;
default:
std::cout << "other character" << std::endl;
}

The break statement indicates the end of the statements executed for a case. If you do not specify it, execution will fall through and the following case statements will be executed even though they have been specified for a different case:

    switch(i) 
{
case 1:
std::cout << "one" << std::endl;
// fall thru
case 2:
std::cout << "less than three" << std::endl;
break;
case 3:
std::cout << "three" << std::endl;
break;
case 4:
break;
default:
std::cout << "other" << std::endl;
}

This code shows the importance of the break statement. A value of 1 will print both one and less than three to the console, because execution falls through to the preceding case, even though that case is for another value.

It is usual to have different code for different cases, so you will most often finish a case with break. It is easy to miss out a break by mistake, and this will lead to unusual behavior. It is good practice to document your code when deliberately missing out the break statement so that you know that if a break is missing, it is likely to be a mistake.

You can provide zero or more statements for each case. If there is more than one statement, they are all executed for that specific case. If you provide no statements (as for case 4 in this example) then it means that no statements will be executed, not even those in the default clause.

The break statement means break out of this code block, and it behaves like this in the loop statements while and for as well. There are other ways that you can break out of a switch. A case could call return to finish the function where the switch is declared; it can call goto to jump to a label, or it can call throw to throw an exception that will be caught by an exception handler outside the switch, or even outside the function.

So far, the cases are in numeric order. This is not a requirement, but it does make the code more readable, and clearly, if you want to fall through the case statements (as in case 1 here), you should pay attention to the order the case items.

If you need to declare a temporary variable in a case handler then you must define a code block using braces, and this will make the scope of the variable localized to just that code block. You can, of course, use any variable declared outside of the switch statement in any of the case handlers.

Since enumerated constants are integers, you can test an enum in a switch statement:

    enum suits { clubs, diamonds, hearts, spades }; 

void print_name(suits card)
{
switch(card)
{
case suits::clubs:
std::cout << "card is a club";
break;
default:
std::cout << "card is not a club";
}
}

Although the enum here is not scoped (it is neither enum class nor enum struct), it is not required to specify the scope of the value in the case, but it makes the code more obvious what the constant refers to.