L02c OperatorOverloading
L02c OperatorOverloading
CSCI 104
Operator Overloading
Mark Redekopp
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
Revised: 05/2021
2
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
3
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
6
Function Overloading
• What makes up a signature (uniqueness) of a function
– name
– number and type of arguments
• No two functions are allowed to have the same signature; the
following 5 functions are unique and allowable…
– void f1(int); void f1(double, int);
– void f1(double); void f1(int, int);
• We say that “f1” is overloaded 5 times
• Notes:
• Return type does NOT make signature unique
– int f1(); is considered the same as void f1();
• For member functions, 'const' make signature unique
– int& List::get() int const & List::get() const;
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
7
Operator Overloading
class User{
public:
User(string n); // Constructor
• C/C++ defines operators (+,*,-,==,etc.) that work string get_name();
with basic data types like int, char, double, etc. private:
user.h
int id_;
• C/C++ has no clue what classes we’ll define and string name_;
what those operators would mean for these yet- };
to-be-defined classes
#include “user.h”
– class complex { User::User(string n) {
public: name_ = n;
double real, imaginary;
user.cpp
}
}; string User::get_name(){
return name_;
– Complex c1,c2,c3; }
// should add component-wise
c3 = c1 + c2; #include<iostream>
– class List { #include “user.h”
... int main(int argc, char *argv[]) {
}; User u1(“Bill”), u2(“Jane”);
user_test.cpp
– List l1,l2; // see if same username
l1 = l1 + l2; // should concatenate // Option 1:
if(u1 == u2) cout << “Same”;
// l2 items to l1
// Option 2:
• We can write custom functions to tell the if(u1.get_name() == u2.get_name())
compiler what to do when we use these { cout << “Same” << endl; }
operators! Let us learn how… return 0:
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed. }
8
Two Approaches
• There are two ways to specify an operator
overload function
– Global level function (not a member of any class)
– As a member function of the class on which it will
operate
• Which should we choose?
– It depends on the left-hand side operand (e.g.
string + int or iostream + Complex )
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
9
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
11
Overloading Notes
• You can overload any operator except the member
operator (.), the scope operator (::), and the ternary
operator ( ? : )
– Binary operators: +, -, *, /, ++, --
– Comparison operators: ==, !=, <, >, <=, >=
– Assignment: =, +=, -=, *=, /=, etc.
– I/O stream operators: <<, >>
• You cannot change the operators precedence
– Multiply must always come before addition
• More questions: https://isocpp.org/wiki/faq/operator-overloading
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
12
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
13
int main()
{
Complex c1(2,3);
Complex c2(4,5);
// equiv. to c1.operator==(c2);
if(c1 == c2)
cout << “C1 & C2 are equal!” << endl;
return 0;
}
Practice On Own
• In the online exercises, add the following
operators to your Str class
– operator[]
– operator==(const Str& rhs);
– If time do these as well but if you test them they
may not work…more on this later!
– operator+(const Str& rhs);
– operator+(const char* rhs);
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
16
Non-Member Functions
int main()
• What if the user changes the {
Complex c1(2,3);
order? Complex c2(4,5);
Complex c3 = 5 + c1;
– int on LHS & Complex on RHS // ?? 5.operator+(c1) ??
– No match to a member function // ?? int.operator+(c1) ??
// there is no int class we can
b/c to call a member function // change or write
the LHS has to be an instance of
that class return 0;
}
• We can define a non- Doesn't work without a new operator+ overload
member function (global Complex operator+(const int& lhs, const Complex &rhs)
scope function) that takes in {
Complex temp;
two parameters (both the temp.real = lhs + rhs.real; temp.imag = rhs.imag;
return temp;
LHS & RHS) }
– May need to declare it as a int main()
{
friend Complex c1(2,3);
Complex c2(4,5);
Complex c3 = 5 + c1; // Calls operator+(5,c1)
return 0;
}
Still a problem with this code
Can operator+(…) access Complex's private data?
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
17
Friend Functions
• A friend function is a class Silly
{
function that is not a public:
member of the class but Silly(int d) { dat = d };
friend int inc_my_data(Silly &s);
has access to the private private:
int dat;
data members of instances };
of that class
// don't put Silly:: in front of inc_my_data(...)
• Put keyword ‘friend’ in // since it isn't a member of Silly
int inc_my_data(Silly &a)
function prototype in class {
Notice inc_my_data is NOT a
s.dat++;
definition return s.dat; member function of Silly. It's a
• Don’t add scope to } global scope function but it
now can access the private
function definition int main()
class members.
{
Silly cat(5);
//cat.dat = 8
// WON'T COMPILE since dat is private
int x = inc_my_data(cat);
cout << x << endl;
}
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
18
Non-Member Functions
class Complex
• Revisiting the previous {
public:
problem Complex();
Complex(double r, double i);
// this is not a member function
friend Complex operator+(const int&, const Complex& );
private:
double real, imag;
};
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
20
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
21
Ostream Overloading
class Complex
• Can define operator {
public:
functions as friend Complex();
Complex(double r, double i);
functions Complex operator+(const Complex &rhs) const;
friend ostream& operator<<(ostream&, const Complex &c);
• LHS is 1st arg. private:
int real, imag;
• RHS is 2nd arg. };
• Use friend function so LHS ostream& operator<<(ostream &os, const Complex &c)
{
can be different type but os << c.real << “,“ << c.imag << “j”;
still access private data //cout.operater<<(c.real).operator<<(“,”).operator<<...
return os;
• Return the ostream& (i.e. }
Member or Friend?
Should I make my operator overload be a member of a class, C1?
C1 objA; C1 objA;
objA << objB // or objB << objA // or
objA + int int + objA
YES the operator overload function NO the operator overload function should
can be a member function of the C1 be a global level (maybe friend) function
class since it will be translate to such as operator<<(cout, objA). It cannot
objA.operator<<(…) be a member function since it will be
translate to objB.operator<<(…).
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
24
Summary
• If the left hand side of the operator is an instance of that class
– Make the operator a member function of a class…
– The member function should only take in one argument which is the RHS
object
• If the left hand side of the operator is an instance of a different
class
– Make the operator a friend function of a class…
– This function requires two arguments, first is the LHS object and second is
the RHS object
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
25
SOLUTION
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
26