What you'll learn
Decisions turn data into behavior. C++ offers simple branches, multi-way selection, scoped domain choices, and short-circuit operators—but readable conditions and explicit invariants matter more than clever expressions.
By the end, you'll be able to:
- Build complete decision chains with
if,else if, andelse - Combine and guard conditions with Boolean operators
- Use decision initializers to keep temporary state local
- Model fixed choices with
enum classandswitch
Conditions & bool
A condition is contextually converted to bool. Comparisons already produce a Boolean result, so write if (ready) instead of if (ready == true).
| Expression | Meaning |
|---|---|
left == right | equal values |
left != right | different values |
left < right | left is less |
value >= low && value <= high | inclusive range |
!ready | logical negation |
Watch out
=; equality uses ==. An assignment can sometimes appear as a condition, so keep warnings enabled and avoid burying assignments inside tests.if, else if & else
An if chain evaluates conditions from top to bottom and executes only the first matching branch. Order overlapping tests from most specific or highest threshold to least.
#include <iostream>
int main() {
int score{87};
if (score >= 90) {
std::cout << "Grade A\n";
} else if (score >= 80) {
std::cout << "Grade B\n";
} else if (score >= 70) {
std::cout << "Grade C\n";
} else {
std::cout << "Keep practicing\n";
}
}Key idea
else expresses the complete remaining case. Add it when every input needs an outcome; omit it when doing nothing is a deliberate valid result.Logical operators
&& requires both conditions, || requires at least one, and! negates a Boolean value. Name an important compound rule when doing so makes the code read like the domain.
#include <iostream>
int main() {
int age{22};
bool has_ticket{true};
bool suspended{false};
bool admitted{age >= 18 && has_ticket && !suspended};
bool needs_help{age < 18 || !has_ticket};
std::cout << std::boolalpha
<< admitted << ' ' << needs_help << '\n';
}| A | B | A && B | A || B |
|---|---|---|---|
| false | false | false | false |
| false | true | false | true |
| true | false | false | true |
| true | true | true | true |
Short-circuit guards
C++ evaluates logical operands left to right. For &&, a false left operand decides the result; for ||, a true left operand decides it. The right side is then skipped.
#include <iostream>
int main() {
int total{120};
int count{0};
// count != 0 is evaluated first. Division runs only when safe.
if (count != 0 && total / count >= 60) {
std::cout << "Passing average\n";
} else {
std::cout << "No passing average available\n";
}
}Watch out
total / countbefore discovering that count is zero.Decision initializers
C++17 and later allow an initializer before the condition in if andswitch. The introduced name stays inside the whole decision, minimizing scope.
#include <iostream>
int main() {
if (int score{84}; score >= 60) {
std::cout << "Passed with " << score << '\n';
} else {
std::cout << "Not yet: " << score << '\n';
}
// score is not visible here; its scope is the entire if statement.
}Tip
switch statements
switch selects among constant integral or enumeration cases. It is a good fit for one value with several discrete choices, not numeric ranges or unrelated conditions.
#include <iostream>
int main() {
char command{'s'};
switch (command) {
case 'n':
std::cout << "New document\n";
break;
case 's':
std::cout << "Save document\n";
break;
case 'q':
std::cout << "Quit\n";
break;
default:
std::cout << "Unknown command\n";
break;
}
}Watch out
break, execution continues into the next case. When fallthrough is intentional, state it with [[fallthrough]];; otherwise terminate the branch.Scoped enumerations
An enum class creates a distinct type with scoped names. Unlike an unscoped enum, its values do not leak into the surrounding scope or convert implicitly to integers.
#include <iostream>
enum class TrafficLight { red, yellow, green };
int main() {
TrafficLight light{TrafficLight::green};
switch (light) {
case TrafficLight::red:
std::cout << "Stop\n";
break;
case TrafficLight::yellow:
std::cout << "Prepare to stop\n";
break;
case TrafficLight::green:
std::cout << "Go\n";
break;
}
}Key idea
enum class when a value must be exactly one choice from a small known set. The type prevents mixing unrelated concepts that happen to use the same underlying numbers.Conditional expressions
The conditional operator chooses one of two expressions and produces a value. It is useful for a short local choice; use an if statement when branches require multiple actions or nested conditions.
#include <iostream>
#include <string_view>
int main() {
int items{3};
std::string_view noun{items == 1 ? "item" : "items"};
int fee{items > 5 ? 0 : 4};
std::cout << items << ' ' << noun
<< ", delivery fee: $" << fee << '\n';
}Common pitfalls
- Always use braces, even for one-statement branches
- Do not compare computed floating-point values with exact equality
- Avoid comparing signed negative values with unsigned sizes
- Keep conditions positive and named when several negations obscure meaning
- Do not repeat an expensive or state-changing function call in several branches
#include <cmath>
#include <iostream>
bool approximately_equal(double left, double right, double tolerance) {
return std::abs(left - right) <= tolerance;
}
int main() {
double result{0.1 + 0.2};
std::cout << std::boolalpha
<< approximately_equal(result, 0.3, 1e-12) << '\n';
}Note
Recap & quick check
Key takeaways
- An if chain executes only the first matching branch.
- Logical operators combine Boolean rules and short-circuit from left to right.
- Decision initializers keep temporary state within the decision's scope.
- switch fits discrete integral or enumeration choices; enum class creates a strong scoped domain type.
- The conditional operator chooses a value; statements handle larger behavioral branches.
Quick check
1. Why must count != 0 appear first in count != 0 && total / count > 5?
2. What does enum class primarily provide?
3. When is switch a good fit?
4. What is the scope of a variable declared in an if initializer?
Your programs can now choose deliberately. Next: Module 5 — Loops & Iteration, where the same reasoning controls repeated work.