Я вижу следующие различия:
1. в switch/case при сравнении могут участвовать только переменные целого типа, а в if/else - любого;
2. switch позволяет проверять только равенство, в то время как if/else может проверять отношения больше/меньше и другое (например if(is_prime_number(n) - со switch такое не сделать);
- если switch подходит - то обычно читается лучше, чем длинная портянка из if/else, сравним:
и
Но вот если появится условие типа (a > 6 && a < 9) - то switch не годится.
3. ряд компиляторов предупредит вас о возможной ошибке в таком случае:
enum SomeEnum { V1, V2, V3 }
//...
Предупредит потому, что SomeEnum может также значение V3 принимать, но вы его не обрабатываете и секции default нет.
4. после break из любой ветви switch вы попадаете в одну и ту же точку программы. С портянкой из if все не так - ведь в примере выше, даже если проверка if (a == 2) завершится успешно - следом проверится a==3 и a==4. Это не эффективно. Можно, конечно использовать замес if/else + goto (метку поставить в нужное место) - но это плохой код. Так делать не стоит, т.к. код читаться вообще не будет.
На заметку 1. Писать можно еще и так:
Если после case нет break - то выходит что-то типа составного условия
Ряд компиляторов в таких случае (если нет break) выдаст вам предупреждения (он предположит, что break вы просто забыли). Выдаст при определенных опциях компиляции - если не нравится, можно опции поменять, а можно использовать [[fallthrough]] - эта штука появилась в С++17.
На заметку 2. Если функция только то и делает, что выполняет проверку параметров с помощью switch или if - то часто целесообразно таки использовать if, т.к. ветку else можно опустить, а код получается вполне читаемый (если каждая ветка завершается оператором return):
Такой код часто встречается, например в шаблоне проектирования "Фабрика" или, например "Цепочка обязанностей".
На заметку 3. Есть "говнокодерский" вариант - как замутить (иначе не назвать) что-то типа switch (в том плане, что переход с конца любой ветви выполнится в одну точку, но чтобы сравнение выполнялось всяко разно - например, a<b и всякие составные условия). Вот этот вариант:
Такой вариант я видел во вполне адекватном коде, но опыты показали, что большинство программистов увидев это скажут что-то нецензурное ))