Module 5 — Operators and Static Members¶
After this module your own types behave like built-in types where that genuinely helps — printable, comparable and sortable — and you can use class-level state without guessing what
staticdoes.
At a glance¶
| Prerequisites | Module 4 |
| Estimated study time | 8–10 hours |
| Lab | Lab 5 — sortable, searchable, printable domain types |
| Exercises | Three tiers — warm-up, core, challenge |
| Cognitive levels | L2 Apply → L5 Design — exit level L4 Analyze |
| Self-assessment | Module quiz |
Why this module matters¶
You have a Book type. There are three things you will want constantly:
to print it, to compare two of them, and to search or sort a collection of them.
Without operator overloading, each of those becomes a named free function that
every caller has to remember — printBook(b), booksEqual(a, b) — and none of
them works with the standard library, which knows only about operators.
Overloading teaches your type the vocabulary C++ already speaks. std::cout << b
then works, std::sort then works, and a == b reads like comparison of
integers. That is the whole benefit, and it is a real one.
It is also the feature most often abused. You will learn where the line is: an overload that means what a reader expects is clarity; one that means something surprising is a bug with a friendly syntax.
The second half of the module, static, is small but frequently misunderstood.
A static data member belongs to the class, not to each object, and that
single fact explains both its usefulness (counters, shared configuration) and its
pitfalls (unexpected sharing, and a definition rule that pre-C++17 code states
awkwardly).
Learning objectives¶
By the end of this module you will be able to:
- Explain the purpose of operator overloading and state when overloading a given operator would be a mistake.
- List the operators that cannot be overloaded (
::,.,.*,?:,sizeof,typeid,alignof, and the named casts). - State the rule that an overloaded operator must have at least one parameter of class or enumeration type.
- Choose correctly between a member function and a free function for a given
operator, and explain why
operator=,operator[],operator()andoperator->must be non-static members. - Overload
<<as a free function takingstd::ostream&, and returnstd::ostream&so that chaining works. - Distinguish
operator=(assignment to an existing object) from a copy constructor (creating a new one), and write an assignment operator that is correct under self-assignment. - Provide
operator==andoperator<so a type works with standard algorithms, and explain whystd::sortneeds a strict weak ordering. - Overload
operator[]in bothconstand non-constforms. - Write a functor with
operator(), and explain how it relates to the lambdas of Module 14. - Declare and define
staticdata members andstaticmember functions, including the C++17inline staticform. - Explain why a
staticmember function has nothispointer.
Core concepts¶
- Operator function — a function named
operator@for some operator@. Overloading is just function definition with unusual syntax. - Member vs free operator — a member overload makes the left operand
*this; a free overload names both operands. Symmetric operations, and any operation whose left operand is not your type, must be free. operator<<for output — free, takesstd::ostream&and returns it, sostd::cout << a << bworks. Usually needsfriendaccess, or public getters.operator>>for input — free, takesstd::istream&, and must handle the failure state of the stream.operator==andoperator!=— equality. Implement==first; deriving!=from==is both shorter and harder to get inconsistently wrong.operator<— ordering. Required to be a strict weak ordering for the standard algorithms and containers to behave.operator[]— element access. Provide theconstand non-constpair so thatconstobjects can be read but not written.operator()— makes an object callable, like a function ("functor"). The basis of the predicates and comparators used throughout Module 14.- Conversion operator —
operator T(); lets an object convert to another type. Powerful and easy to abuse; prefer a named function unless the conversion is obvious. operator=— assignment. Must be a non-static member, must handlea = a, and its interaction with the copy constructor is the subject of Module 10.- Self-assignment —
a = a. Harmless for simple types, fatal for classes that free a resource before copying the new one in. staticdata member — one storage location per class, shared by every object. Must be defined exactly once outside the class, unless declaredinline(C++17) orconstexpr.staticmember function — belongs to the class rather than an object, has nothis, and therefore cannot beconstand cannot touch non-static members.- Class-level state — for counters, shared configuration, and named
constructors. A
staticfactory function is the smallest useful design pattern in the course, and the seed of Module 15.
Module contents¶
| Section | What it contains |
|---|---|
| Introduction (this page) | Overview, prerequisites, objectives, concept inventory |
| Concepts and explanations | Overloading rules, member versus free, strict weak orderings, copy construction versus assignment, static members, the four operators to leave alone |
| Worked examples | Four programs — a class-level counter, money that prints and sorts, a failed read that is not a rollback, and a measurement of what overloading && costs — plus a member-versus-free design table |
| Code examples | examples/module-05/ — four programs, each with captured output that the build verifies |
| Misconceptions and mistakes | Eight wrong mental models, ten symptoms, and four worked mistakes with their real compiler messages |
| Debugging | Testing a comparator as a relation, the three failure classes, and the escalation ladder |
| Exercises | Three tiers, including an invalid comparator to record and a link error to fix twice |
| Lab 5 | The catalogue becomes sortable, searchable and printable — and the broken comparator is a deliverable |
| Challenge problems | A type with three meaningful orders, an inconsistency hunt, and an identifier scheme for two translation units |
| Self-assessment | Nine questions, including two predictions |
| Summary | What must be retained, the terms to be able to define, and the checklist |
| Further reading | Books and official documentation |
What you can do after this module¶
- Print any of your own types with
std::cout << obj. - Sort and search a collection of your own types using the standard library.
- Write an assignment operator that survives self-assignment.
- Count how many objects of a class currently exist, using a
staticcounter — and explain why that counter is not per-object. - Reject an overload proposal with a reason other than taste.
Where this is used later¶
operator<and==are prerequisites for using your types instd::map,std::setand the algorithms of Module 14.operator=and self-assignment are the entry point to the Rule of Three in Module 10.operator<<is reused for file output in Module 16, and for describing objects in tests.operator()becomes lambdas and comparators in Module 14.staticfactory functions grow into the factory pattern in Module 15.
Common mistakes to watch for¶
| Symptom | Cause |
|---|---|
error: 'operator<<' must have an argument of class or enumerated type |
Both operands are built-in types. At least one must be one of yours |
error: 'operator=' must be a non-static member function |
operator=, operator[], operator() and operator-> are declared as free functions |
std::sort compiles but crashes or misbehaves |
operator< is not a strict weak ordering — for example it returns true for equal elements |
error: 'operator<<' must take exactly one argument |
It was written as a member function. It usually needs to be free |
A static member linker error: undefined reference to 'Book::count' |
The static member was declared but never defined outside the class (pre-C++17 style), or not declared inline/constexpr |
error: invalid use of member in static member function |
A static function has no this, so it cannot touch non-static members |
| A counter jumps unexpectedly | A copy was made. Count copies once constructors and the copy constructor are covered in Module 10 |
Skills checklist¶
Levels this module works at: [L2 Apply → L5 Design] — see How you will learn.
Tick an item only when the evidence exists:
- [ ] I can overload
==,<and<<so my own type works with standard algorithms — evidence: a sorted, printed vector of my own objects - [ ] I can say which operators must be members and which should be free, by naming the left operand — evidence: challenge X2's eight decisions, with reasons
- [ ] I can write a valid comparator and test it as a relation — evidence: your duplicate-containing sort, plus the twenty-line property test
- [ ] I can explain why an invalid comparator is undefined behaviour, and why a wrong order is the lucky outcome — evidence: your Lab 5 comparator note
- [ ] I can tell copy construction from copy assignment on any line of code —
evidence: the
Tracktrace, predicted before it was run - [ ] I can declare, define and use a
staticdata member, in either the classic or the C++17 form — evidence: the identifier counter, and your reason for the form you chose - [ ] I can explain why a
staticmember function has nothis— evidence: a written explanation with a checkable consequence (challenge X1) - [ ] I can refuse an overload proposal with a reason a reader can follow — evidence: the four operators you must not overload, with the guarantee each one would destroy
Suggested next step¶
Previous: Module 4 — Encapsulation · Next: Module 6 — Inheritance · All modules: Modules index
Module 6 assumes your types have real interfaces, honest comparisons and no
contradiction between ==, < and printing — because it is about to build families
of them. Lab 5's catalogue holds one kind of item; Lab 6 needs several, and the
question of what a book, a journal and a DVD genuinely share is the first design
question in this course with no single right answer.