Lecture 15 - Oct 10, 2023
Summary
In this lecture, we continue our discussion on operator overloading. We also discuss when we need friend functions.
Last lecture
Dynamic memory allocation and operator overloading.
Today
operator=
and operator<<
.
Operator overloading
Recall operator+
: x + y <=> x.operator+(y)
.
class Complex {
private:
double real;
double img;
public:
() { real = 0.0; img = 0.0; }
Complex(double r, double i) { real = r; img = i; }
Complex
// pass by reference to avoid copying
// memory efficient
operator+(const Complex& c) const {
Complex return Complex(real + c.real, img + c.img);
}
}
Passing by value will create a copy of rhs.
This is memory inefficient if the object has many data members.
Pass by reference will not create a copy, so it is memory efficient.
Good practice for safety
Pass the object as a const object
::operator+(const Complex& rhs) {
Complex Complex.real = 0; // compile-time error!
rhsreturn Complex(real + rhs.real, img + rhs.img);
}
Operator plus does not change members of the object
Use const
modifier to prevent changes to members of the object.
::operator+(const Complex& rhs) const {
Complex Complex= 0; // compile-time error!
real return Complex(real + rhs.real, img + rhs.img);
}
int main() {
(3,5), y(4,6), z;
Complex x= x + y; // now we have operator=
z }
Overloading operator equal
By default, operator=
is there. It sets all the data members in the object to the data members of the right hand side object.
How does the default assignment operator=
look like?
z = x
(left hand side = right hand side) is equivalent to z.operator=(x)
.
How to allow chain assignments?
y = (z = x)
should return object z
.
This is a keyword and a pointer pointing to the object on which the function was invoked (i.e., z
in z = x
).
// Return by reference: Complex&, which is the object itself
& Complex::operator=(const Complex& rhs) {
Complex= rhs.real;
real = rhs.img;
img return *this; // returns object z
}
Overloading operator insertion
(3,4);
Complex z
// with standard operator <<
// RHS: Complex
// LHS: ostream (not Complex)
<< z; cout
cout
is an object of ostream
class.
operator<<
cannot be a member function of complex, since LHS is of type ostream
.
operator<<
cannot be a non-member function as it has to access private members of Complex
.
Solution: operator<<
can be a friend
function.
A friend
function can access private members of an object, and LHS
can be a non-complex type.
class Complex {
...
public:
friend ostream& operator<<(ostream& os, const Complex& x);
};
& operator<<(ostream& os, const Complex& x) {
ostream<< "(" << x.real << "," << x.img << ")";
os return os;
}
Remember that operator<<
is not a member, so there is no need for Complex::
.
int main() {
(3,4);
Complex z<< "z = "<< z << endl;
cout }
cout
is returned to allow chained cout
.
cout
(and all other streams) cannot be passed or returned by value. Only by reference, as their copy constructor is deleted.
Exercise
Implement operator==
.
class Complex {
...
public:
...
bool operator==(const Complex& rhs) const {
return (real == rhs.real) && (img == rhs.img);
}
};