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.
Arguments
- An operator can be defined as a method or a plain function.
- A unary operator (such as
!
) has one operand:
- If it’s a free function, it has one argument, the only operand.
- If it’s a method, the operand is the current object,
and the method has no arguments.
- A binary operators (such as
/
) has two operands:
- If a free function, it has two arguments, the left & right operands.
- If a method, the left operand is the current object,
and the right operand is the only argument to the method.
- Make an operator a method, unless you can’t.
- It can’t be a method if the left operand is a built-in type,
because built-in types don’t have methods.
- It can’t be a method if the left operand is not your class,
because that class is already written. You can’t add to it.
Arguments
Foo f;
Bar b;
result = f + b;
There are two ways to implement the binary +
operator:
operator+(const Foo &, const Bar &); //
free function, two arguments
Foo::operator+(const Bar &) const; //
Foo
method, one argument
Of course, they each need a return type.
The method should const, since +
doesn’t alter its left operand,
unless you have extremely peculiar semantics.
Arguments
Foo f;
result = *f;
There are two ways to implement the unary *
operator:
operator*(const Foo &); //
free function, one argument
Foo::operator*(); //
Foo
method, no arguments
Return types are needed, and the method might be const,
depending on the semantics.
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
The Hagia Sophia
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.
This will call a.operator+=(b)
:
This will call a.operator=(b.operator-(c))
:
Fraction a, b, c
a = b - 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 operators 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.