++aCnt; //
case 'e':
++eCnt; //
case 'i':
++iCnt; //
case 'o':
++oCnt; //
case 'u':
++uCnt;
}
Чтобы понять происходящее, предположим, что значением переменной ch
является 'e'
. Выполнение переходит к коду после метки case 'e'
, где происходит инкремент переменной eCnt
. Выполнение продолжается далее через метки case
, увеличивая также значения переменных iCnt
, oCnt
и uCnt
.
break
и не обязателен после последней метки оператора switch
, использовать его все же рекомендуется. Ведь если впоследствии оператор switch
будет дополнен еще одной меткой case
, отсутствие оператора break
после прежней последней метки не создаст проблем.
default
Операторы после default
выполняются, если ни одна из меток case не соответствует значению выражения оператора switch
. Например, в рассматриваемый код можно добавить счетчик негласных букв. Значение этого счетчика по имени otherCnt
будет увеличиваться в случае default
:
//
switch (ch) {
case 'a': case 'e': case 'i': case 'o': case 'u':
++vowelCnt;
break;
default:
++otherCnt;
break;
}
В этой версии, если переменная ch
не содержит гласную букву, управление перейдет к метке default
и увеличится значение счетчика otherCnt
.
default
имеет смысл создавать всегда, даже если в нем не происходит никаких действий. Впоследствии это однозначно укажет читателю кода, что случай default
не был забыт, т.е. для остальных случаев никаких действий предпринимать не нужно.
Метка не может быть автономной; она должна предшествовать оператору или другой метке case
. Если оператор switch
заканчивается разделом default
, в котором не осуществляется никаких действий, за меткой default
должен следовать пустой оператор или пустой блок.
switch
Как уже упоминалось, выполнение оператора switch
способно переходить через метки case
. Когда выполнение переходит к некой метке case
, весь расположенный выше код оператора switch
будет проигнорирован. Факт игнорирования кода поднимает интересный вопрос: что будет, если пропущенный код содержит определение переменной?
Ответ прост: недопустим переход с места, где переменная с инициализатором уже вышла из области видимости к месту, где эта переменная находится в области видимости.
case true:
//
//
string file_name; //
//
int ival = 0; //
//
int jval; //
break;
case false:
//
jval = next_num(); //
if (file_name.empty()) //
//
// ...
Если бы этот код был допустим, то любой переход к случаю false
обходил бы инициализацию переменных file_name
и ival
, но они оставались бы в области видимости и код вполне мог бы использовать их. Однако эти переменные не были бы инициализированы. В результате язык не позволяет перепрыгивать через инициализацию, если инициализированная переменная находится в области видимости в пункте, к которому переходит управление.
Если необходимо определить и инициализировать переменную для некоего случая case
, то сделать это следует в блоке, гарантируя таким образом, что переменная выйдет из области видимости перед любой последующей меткой.
case true:
{
// ok
string file_name = get_file_name();
// ...
}
break;
case false:
if (file_name.empty()) //