Г
Грокаем C++
@grokaemcpp9.3K подп.
3.3Kпросмотров
35.4%от подписчиков
12 марта 2026 г.
questionScore: 3.6K
Как применять switch? #новичкам Мы вспомнили про switch и некоторые его особенности. Теперь посмотрим, в каких сценариях их адекватно применять и как это делать. Для начала повторим ограничения. switch может работать только с целочисленными значениями и перечислениями. В основном, конечно, с перечислениями как с именованными числами. В коде не должно быть магических чисел, каждая ветка должна иметь наглядную семантику, а перечисления помогают "называть" числа без неконтролируемого размножения локальных или статических переменных. В прошлом посте мы свичались по http статус кодам. Тогда они были просто числами, так было проще вспомнить механику этой инструкции. Давайте перепишем в нормальный вид: switch(status_code) { case HTTPStatus::OK: processSuccess(); break; case HTTPStatus::BadRequest: case HTTPStatus::Unauthorized: case HTTPStatus::Forbidden: case HTTPStatus::NotFound: logClientError(status_code); break; case HTTPStatus::InternalServerError: case HTTPStatus::BadGateway: case HTTPStatus::ServiceUnavailable: return logServerError(status_code); default: // ... } Теперь магических чисел нет. Плюс к этому все кейсы должны быть известны на этапе компиляции. Динамически менять ничего не получится. Эти особенности уже так сильно ограничивают применение switch'а. Он идеален в критичных к производительности местах и в плотных целочисленных диапазонах(тогда он хорошо оптимизируется). Дальше идем. Чем вообще может быть плох switch? 👉🏿 Его использование смешивает логику выбора и обработки. Это может быть нормой при небольшом количестве веток. Все находится рядышком, не нужно прыгать по коду, чтобы понять полную картину. Но это совершенно точно становится проблемой, когда количество кейсов больше 10-20. Свитч целиком перестает помещаться на экран и вместо того, чтобы при чтении кода понимать логику работы кода, вы разбираетесь в том, какой обработчик для каждого кейса вызывается. 👉🏿 Расширение кейсов требует изменения клиентского кода. Опять же, при небольшом количестве веток - ничего страшного. Но с увеличением объема растет количество деталей, которые разработчик держит у себя в голове при чтении кода. У нас и так профессия сложная, давайте разгружать друг другу мозг. Код не должен меняться, если у вас ожидаемо вдруг появился новый кейс. 👉🏿 Много кейсов - много кода. Особенно если писать инструкции обработчиков прям внутри кейсов. Много кода в одном месте - почти всегда очень плохо читается. Из этих проблем можно сделать несколько выводов: 1️⃣ Если мало кейсов и в обработчиках мало кода(1-2 строчки) оставляйте как есть. 2️⃣ Если обработчики большие, то всегда выносите их в отдельные функции. Помните, что есть метрика "количество строк в функции" и она редко должна превышать 15-20 строк. 3️⃣ Если у вас много кейсов, то вынесите свитч в отдельную функцию с подходящим названием. Тогда вы скроете эту большую простыню из логики кода. И она будет описываться одним вызовом функции, по имени которой будет понятно, что вы хотите сделать. void dispatch(Editor &editor, Command cmd) { switch (cmd.type) { case Command::NewFile: executeNewFile(editor); return; case Command::OpenFile: executeOpenFile(editor); return; // ... } } void processUserInput(Editor &editor, UserInput input) { if (auto cmd = interpretInput(input)) { dispatch(editor, *cmd); } } Когда не надо применять switch? 🔞 Пользовательский тип под условием. 🔞 Кейсы накидываются или выкидываются динамически(например из конфигурации) 🔞 Если нужен какой-то дикий полиморфизм, когда обработчик полиморфно выбирается на основе значения кейса. В этих случаях обычно используют статическую std::unordered_map, сопоставляя значения кейсов их обработчикам. Use the right tool. Stay cool. #cppcore #goodpractice #design
3.3K
просмотров
3894
символов
Нет
эмодзи
Нет
медиа

Другие посты @grokaemcpp

Все посты канала →
Как применять switch? #новичкам Мы вспомнили про switch и не — @grokaemcpp | PostSniper