Фантазии на тему switch
От: tarkil Россия http://5209.copi.ru/
Дата: 09.06.05 11:13
Оценка: 1 (1)
Коль уж пошла такая синтаксическая пьянка, то хочу (просто в порядке фантазии) обсудить конструкцию switch в C++. Главная, как мне кажется, неприятность этой конструкции в том, что нужно после каждого case писать по break. Это и забывают нередко, к тому же.

Но, с другой стороны, необязательность break даёт две фишки:
— использовать один case, как фрагмент другого
— ставить несколько меток одному и тому же коду

Чтоб не быть голословным, придумаю пример — по коду причины отказа нужно вычислить текст отказа и некоторый условный "вес", тяжесть этой причины. Код несколько надуманный, но уж что пришло в голову под конец рабочего дня

string text; // текст причины
unsigned reasonWeight = 0; // "тяжесть" причины

switch( reasonCode )
{
    case REASON_1:
    case REASON_2:
        text = "Текст главной причины отказа";
        reasonWeight = 1000;
        break;
    case REASON_3:
        text = " (но с дополнением)";
        reasonWeight = 500;
    case REASON_4:
        text = "Текст второстепенной причины" + text;
        reasonWeight += 1000;
        break;
    case REASON_5:
        text = "А, считай и не причина"; // вес остался нулевым по умолчанию
        break;
    default:
        text = "(встречен отказ с неизвестным кодом)";
        reasonWeight = REASON_WEIGHT_MAX;
}

Фактически, мы тут имеем goto на метку. Не знаю, как вам, но мне поведение case REASON_3, case REASON_4 кажется несколько ненаглядным, что ли...

Предлагаю вариант улучшения номер раз.

string text; // текст причины
unsigned reasonWeight = 0; // "тяжесть" причины

switch( reasonCode )
{
    mixin addAppendix
    {
        reasonWeight += 500;
        text += " (но с дополнением)";
    }
    case REASON_1, REASON_2:
        text = "Текст главной причины отказа";
        reasonWeight = 1000;
    case REASON_3: addAppendix();
    case REASON_4:
        text = "Текст второстепенной причины"
        reasonWeight = 1000;
        addAppendix();
    case REASON_5: text = "А, считай и не причина";
    default:
        text = "(встречен отказ с неизвестным кодом)";
        reasonWeight = REASON_WEIGHT_MAX;
};

Мало того, что код стал компактней, так за счёт миксина (видимого только внутри данного switch) он ещё и приобрёл привычный процедурный стиль, addAppendix теперь выделен в особую сущность с чётко определёнными функциями. Не нравятся миксины? Ну, никто не отменял макросы

Однако, мне тут продолжает не нравится нагромождение ключевых слов case... тут бы по пустой строке между ними вставить, но это почти убивает пользу от исключения break...

Поэтому, смотрите вариант номер два.

string text; // текст причины
unsigned reasonWeight = 0; // "тяжесть" причины

mixin addAppendix
{
    reasonWeight += 500;
    text += " (но с дополнением)";
}

switch( reasonCode )
REASON_1, REASON_2 {
    text = "Текст главной причины отказа";
    reasonWeight = 1000;
}
REASON_3 { addAppendix(); }
REASON_4 {
    text = "Текст второстепенной причины"
    reasonWeight = 1000;
    addAppendix();
}
REASON_5 { text = "А, считай и не причина"; }
default {
    text = "(встречен отказ с неизвестным кодом)";
    reasonWeight = REASON_WEIGHT_MAX;
};

Обращаю внимание на ";" в конце — это признак конца оператора.

Что лучше не стало? Жаль. У кого какие ещё будут фантазии на тему?
--
wbr, Peter Taran
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.