Operator Overloading: Semantics First
intermediate25 min readLesson 87 of 204
When an operator earns its place; member vs non-member; consistent operator families.
Operators are ordinary functions with special names. Overloading them lets your types read like the built-ins โ but only when the meaning is obvious.
class Money {
public:
explicit Money(long cents) : cents_{cents} {}
long cents() const { return cents_; }
private:
long cents_;
};
inline Money operator+(const Money& a, const Money& b) {
return Money{a.cents() + b.cents()};
}
inline bool operator==(const Money& a, const Money& b) {
return a.cents() == b.cents();
}
The decision procedure
- Would the operator's meaning be obvious to any reader?
Money + Moneyyes;Money << intno. - Prefer writing it as a non-member on top of the public interface (keeps encapsulation; enables symmetric conversions).
- Members are required only for
=,(),[],->. - Semantic families go together: define
==and!=consistently (C++20 can synthesize!=from==); define<to match=='s ordering idea.
If an operator's semantics would surprise, use a named function instead โ
add_days(date, 3) beats a mysterious date + 3 for a Date where the
calendar rules are nontrivial.