Show Lecture.OperatorFunctions as a slide show.
CS253 Operator Functions
The List
- These operators can be overloaded:
- unary:
+ - *
- binary:
+ - * / % ˆ & | << >>
+= -= *= /= %= ˆ= &= |= <<= >>=
~ !
=
== != < > <= >=
&& ||
++ --
, ->* -> () []
new new[] delete delete[]
""
suffix
Yes, =
is an operator, just like +
is. Sure, =
usually
alters its left operand, whereas +
doesn’t, but C++ doesn’t care
about that.
What can’t you do?
You cannot:
- create new operators (sorry, no
**
, >>>
, or ≠
)
- can’t change the lexical analyzer or parser
- redefine existing bindings (can’t make
"zulu"+3
do concatenation)
- because C++ is extensible, not mutable
- change precedence or grouping of existing operators
- because C++ is extensible, not mutable
Spell it out
- The compiler doesn’t deduce methods from other mathematically-equivalent
methods. That’s your job.
- You have to define every operator that you need.
- Assume that
operator+(const Fraction &, double)
is defined:
Fraction a, b;
a = b + 1.2; // ok
a = 3.4 + b; // bad
- Defining
operator+
does not create operator+=
,
or operator++
.
- Defining preincrement doesn’t even define postincrement!
Use previous work
Consider these addition methods:
Fraction operator+(const Fraction &)
Fraction &operator+=(const Fraction &)
Fraction &operator++() // pre
Fraction operator++(int) // post
The smart programmer will have operator+=
do the real work,
have operator+
and preincrement invoke +=
, and have postincrement
call preincrement.
More re-use
For that matter, define operator-=
in terms of operator+=
(if negation is cheap for your class). Then, as before, you can have
operator-
and predecrement call operator-=
,
and have postdecrement call predecrement.
Methods
When possible, implement operator overloading as methods (as part of the
class). When the method is called, the left operand is *
this
and
the right operand is the argument.
Fraction a, b; a += b;
That will call a.operator+=(b)
.
Fraction a, b, c
a = b - c;
That will call a.operator=(b.operator-(c))
.
Non-member functions
Sometimes, you can’t use a method (method ≠ function, right?):
Fraction a, b;
a = 1.2 + b;
If operator+
were a method, it would have to be a method of
double
. That wouldn’t work, so it must be a non-member function,
a free function:
Fraction operator+(double, const Fraction &);
Of course, you still need the method that handles Fraction+double
.
Function overloading is your friend.
Abuse
Java doesn’t allow operator overloading, supposedly because it’s
too confusing. There is something to be said for that.
Resist the urge to redefine every 💣 ☠†※! operator possible.
Only define those that:
- have clear mathematical analogues
- or mimic existing C++ operators (e.g.,
+=
)
- or make sense by analogy (e.g., file
+
file could
concatenate the contents of two files).
Example of abuse
A misguided programmer might define a-b
, where a
and b
are
strings, to mean “return a
, without the chars that are also in
b
”.
string operator-(string a, const string &b) {
for (size_t p=0; (p = a.find_first_of(b, p)) != a.npos;)
a.erase(p, 1);
return a;
}
int main() {
const string name = "Bjarne Stroustrup";
cout << name-"aeiou" << '\n';
}
Bjrn Strstrp
Maybe, maybe not. 🤷 Call it remove_chars()
, instead.