A class invariant is a condition that must hold whenever an object is usable: after construction and between every sequence of method calls. It defines a consistent, meaningful state for the object’s data and behavior. section 7.2.1 section 7.2
Establish and protect the invariant through the class interface:
- Constructors initialize every instance variable with a meaningful value or reject construction when valid initialization is impossible. section 7.2.2 section 10.2
- Mutators validate inputs and leave state unchanged or signal failure when a value falls outside the permitted range. section 7.3
- Keep representation knowledge inside the class; unnecessary accessors, public state, and protected variables let clients or derived classes bypass its rules. section 8.2 section 8.4
- Treat copying, assignment, inheritance, and resource ownership as invariant-sensitive operations rather than automatic implementation details. section 8.0 section 7.6
A Person must never have a negative age
A Person class can require an age in its constructor and validate it before initialization. Constructing Person("Joey", -1) then throws instead of creating a partially initialized object. The same rule must govern later state changes; a default constructor that leaves age undefined merely shifts responsibility to callers and makes invalid use easy.
Listing 7.1 A typical textbook structure
struct Person {
int age;
std::string name;
};
int main() {
Person p1;
std::cout << p1.age << " '" << p1.name << "'\n"; #1
Person p2 = Person();
std::cout << p2.age << " '" << p2.name << "'\n"; #2
}
The listing contrasts a simple aggregate whose default-created Person may contain undefined or meaningless state with a class that enforces valid construction. section 7.3











