INTRO TO COMPUTER SCIENCE II
FRIENDS & OPERATOR OVERLOADING
CS162
Miscellaneous
Midterm
See myself or TAs in office hours to go over specific questions/score
Magic Makefile
On Week 5 – Learning Material
Extra Credit: Memes
Implementing Inheritance
Member access specifiers
Public – accessed by anybody
Private – accessed by only Base functions or friends
This means derived classes can’t access base class private members directly
Protected – allows Derived classes to access members, but not accessible outside the class
Base access specifiers
Public – this is the one we care about Private
Protected
class Base { public:
int pub; private:
int pri; protected:
}; int pro;
class Derived : public Base { public:
Derived(){
pub = 1; //allowed
pri = 2; //not allowed pro = 3; //allowed
}; }
int main(){ Base b;
b.pub = 1; //allowed b.pri = 2; //not allowed b.pro = 3; //not allowed Derived d;
d.pub = 1; //allowed d.pri = 2; //not allowed d.pro = 3; //not allowed
}
Friend Functions
Function that can access the private members of a class as though it were a member of that class
class Point { private:
int x;
int y; public:
Point();
Point(int, int);
~Point();
Point(const Point&);
void move_left(int);
friend void print_location(const Point&);
void print_location(const Point &point){
cout << "Location is " << point.x << "," << point.y <
Full list here: https://en.cppreference.com/w/cpp/language/operators Ones you can’t overload: . .* :: ?:
Operator Overloading
Can only overload operators that exist
At least one of the operands in an overloaded operator must be a user‐
Vocab Refresh:
Precedence determines which operators are evaluated first
Associativity determines the direction in which operators are evaluated (left or right)
defined type
Can’t change the number of operands an operator supports
Can’t change the default precedence and associativity (C++ order of operations)
https://en.cppreference.com/w/cpp/language/operator_precedence
Best Practices:
Keep the function of the operators close to the original intent as possible If the meaning isn’t clear and intuitive, use a named function instead
Operator Overloading
3 ways to overload operators
Member function – mostly used when modifying left operand
Friend function – convenient due to direct access to class members
Normal function – better to use, but only works if you have accessors/getters
How to choose?
If =, [], (), or ‐> use member function
If unary operator, use member function (++)
If binary operator that doesn’t modify left operand, use normal/friend (+)
If binary operator that does modify left operand, but can’t change definition of it, use normal/friend (<<)
If binary operator that does modify left operand, but you can change definition of it, use member function (+=)
Vocab Refresh:
Unary operators act on single operands to make new value Binary operators act on two operands to make new value
Converting from friend to member
friend Point operator+=(const Point& p1, const Point p2){
p1.x = p1.x+p2.x; p1.y = p1.y+p2.y; return p1;
}
Point Point::operator+=(const Point& p2){ this->x = this->x+p2.x;
y = y+p2.y;
return *this;
}
Member function rules
Overloaded operator must be added as a
member function of the left operand
Left operand becomes the implicit *this object
All other operands become function parameters
Steps for converting
Define operator as a member instead of a
friend
Left parameter removed
Inside function, all references to left parameter removed or replaced with *this
&
Operator Overloading – I/O
Printing each member variable of a class on the screen can be annoying cout << “Point” << p.get_x() << “,”<< p.get_y() << endl;
Have used print member functions to get around this
void print(){ cout << “Point” << x << “,” << y << endl; } p.print();
Overload the << operator!
friend ostream& operator<<(ostream& out, const Point& p){
out << “Point” << p.x << “,” << p.y << endl;
return out; }
cout << p << endl;
Some code...
Let’s look at Animals and Monkeys again