Quiz 4 — Answers¶
Q1 — B. An invariant is a statement that must be true of an object for its whole lifetime — "the balance is never negative", "the two arrays are the same length". It is enforced by the operations that change the object, which is why a well-designed class has a small number of places that can break it.
Q2 — False. Returning a & to private data hands the caller a way to write it. The
data is nominally private, but the invariant the class protects can still be broken from
outside — which is the only thing encapsulation is for.
Q3 — A, C, D. A public data member (A) breaks it outright. An accessor returning
std::string& (C) is a hidden door. A setter that accepts any value of the right type
(D) gives the caller back control of the invariant. B is fine: returning const
std::string& allows reading without writing.
Q4 — -87.
The class intends "every member has a positive strength" — that is why add checks
strength > 0. But members() returns a mutable reference, so the caller appends -100
directly, and total() reports 5 + 8 − 100 = −87. The guard in add is bypassed by the
very accessor that was meant to help.
Q5 — Return a const reference (or a copy):
Callers can still read the members, but cannot add, remove or edit them. If a caller
genuinely needs a filtered view, return a new std::vector<int> instead. The point is that
no operation outside the class can now insert a non-positive strength.
Q6 — Enforcing an invariant in one place means there is exactly one line to get right and one line to fix; asking every caller to respect a rule puts the same rule in many places where it can be forgotten, and gives no place to look when it breaks.
Q7 — Encapsulation makes a broken state impossible to construct, not merely discouraged. With true encapsulation there is no expression a caller can write that puts the two fields into contradiction — the compiler has no such expression to accept.
Q8 — It compiles, and prints -5.
The non-const overload returns int&, so s.minutes() = -5; assigns through it. That is
the leak: the value is private, yet freely writable. (Having both a const and a
non-const minutes() is legitimate for a const-correct design, but the non-const one
should not return a mutable reference if the field has an invariant.)
Q9 — Invariant: the start hour is in 0–23 and the duration is in 15–120 minutes. The
single place that enforces it is the constructor (and any setter that changes them).
Mechanism: reject the bad value — throw std::invalid_argument once exceptions are
available, and before that refuse to construct. The key point is that a Slot can never
exist in an invalid state, so no other code needs to re-check.
Q10 — Two related fields, such as a bank account's balance and a lastTransaction:
a mutator for each field lets a caller change one without the other, so the pair can
contradict. Encapsulation is about the operations the class offers, not about providing
an accessor/mutator pair for every field — sometimes the right operation is deposit() and
withdraw(), with no setBalance() at all.
Marking. One point per question (Q3 all-or-nothing). Then read Marking Yourself.