1 Overloading Overloading allows a function or operator to have a different meaning depending on the...
-
Upload
roger-king -
Category
Documents
-
view
216 -
download
3
Transcript of 1 Overloading Overloading allows a function or operator to have a different meaning depending on the...
1
Overloading
Overloading allows a function or operator to have a different meaning depending on the type of objects it is used on. Examples:
operator+ can be applied to both integers and strings. When applied to integers, it adds them. When applied to strings it concatenates them.
We may wish to have more than one constructor for a class, depending on what inputs are specified by the user
2
Overloading
A function with the same name as an existing one but a different number and/or types of parameters is an overloaded instance of the existing function.
If two functions have the same name and same number and types of parameters, they cannot have different return types. This would be an error.
3
Overloading
Example 1: The maximum() function can be used to find the largest of three or the largest of two integers.
int maximum (int x, int y) { return (x>y)? x : y;}
int maximum (int x, int y, int z) { if (x < y) return (y < z)? z : y; else return (x < z)? z : x; }
int main () { cout << maximum(3,4) << endl; cout << maximum(3,8,-1) << endl; return 0;}
screen output: 4 8
4
Overloading
Example 2: Consider a Fraction class. There are several places where we can use overloading:
An additional constructor that takes as arguments initial numerator and denominator values
A plus (+) operator to add two fractions. The output stream operator (<<) to be able to use cout to print a
Fraction.
5
Overloading
Example 2: Overloading constructors
class Fraction { private: int numerator; int denominator; public: Fraction() { numerator = denominator = 1; } Fraction(int num, int den) { numerator = num; denominator = den; } void print() { cout << numerator << "\n--\n" << denominator << endl; } ...};
int main () { Fraction f1; Fraction f2(3,4); f1.print(); cout << endl; f2.print(); return 0;}
screen output:
1--1
3--4
6
Overloading
Example 2: Overloading constructors We may also "merge" the two constructors into one by using default
arguments. Careful! The default arguments must be the last (rightmost ones)
class Fraction { private: int numerator; int denominator; public: Fraction(int num=1, int den=1) { numerator = num; denominator = den; } void print() { cout << numerator << "\n--\n" << denominator << endl; } ...};
int main () { Fraction f1; Fraction f2(3,4); f1.print(); cout << endl; f2.print(); return 0;}
screen output:
1--1
3--4
7
Overloading
Example 3: Overloading the + operator
class Fraction { private: int numerator; int denominator; public: Fraction(int num=1, int den=1) { numerator = num; denominator = den; } Fraction operator+ (const Fraction& addend) { Fraction result; result.numerator = numerator * addend.denominator \ + denominator * addend.numerator; result.denominator = denominator * addend.denominator; return result; } void print() { cout << numerator << "\n--\n" << denominator << endl; } ...};
int main () { Fraction f1(1,4); Fraction f2(3,4); Fraction sum; sum = f1+f2; sum.print(); return 0;}
screen output:16--16
8
Overloading
Example 3: Dissecting the overloaded operator+
Fraction operator+ (const Fraction& addend);
sum = f1+f2; is equivalent to sum = f1.operator+(f2);
Apply operator+ to the current object (f1).Pass the addend, f2, as an argument to the operator.Get back the sum and assign it to a variable.
9
Overloading
Example 4: Overloading the << operator We want to be able to type
cout << f1;instead of
f1.print(); But this is different from the + operator:
cout << f1; is equivalent to operator<<(cout, f1) This means that operator<< cannot be a member of the
Fraction class (as it is not applied on a Fraction object). The overloaded operator<< will be defined globally, outside
the class. Furthermore, it should return a reference to an ostream
object in order to allow chained output (e.g. cout << f1 < f2;)
Why is this safe?
10
Overloading
Example 4: Overloading the << operator
class Fraction {...};
ostream& operator<< ( ostream& out, Fraction frac) { out << frac.getNumerator() << "\n---\n" << frac.getDenominator() << endl; return out;}
int main () { Fraction f1(3,4); cout << f1; return 0;}
screen output:3--4
11
operator=
Consider the following chunk of code:
The assignment is translated to f1.operator=(f2) A copy of f2 is placed and is assigned to f1 The compiler will perform a member by member
assignment This can cause problems when dynamic memory is
involved. We must overload the assignment operator, so that it
performs a deep assignment.
int main () { Fraction f1(3,4); Fraction f2; f2 = f1; return 0;}
12
operator= Example:
class ClassInfo {private:
int *student_ids;int class_size;
public: ClassInfo (int size=0) {
if (size == 0) student_ids = NULL; else student_ids = new int[size];
class_size = size;}void read_ids() {
for (int i=0; i<class_size; i++) { cout << "Enter next id: "; cin >> student_ids[i]; }
}};
int main () { ClassInfo eecs231(5); eecs231.read_ids();
ClassInfo eecs211(3); eecs211.read_ids(); eecs211 = eecs231;
...
13
operator= and pointers1:ClassInfo eecs231(16); eecs231.read_ids();
5
eecs231: 10 9 13 2 7 8
2: ClassInfo eecs211;
3
eecs211: 1 16 3
3: eecs211 = eecs231;
5eecs231: 10 9 13 2 7 8
5
eecs211: 1 16 3
14
operator= and pointers
Not only do both objects point to the same memory, even though they are difference objects, but we also have a memory leak because we lost the original eecs211.student_ids pointer.
We must perform a deep assignment!
15
operator= and pointers
ClassInfo& operator= (const ClassInfo& rhs) {if ( this == &rhs )
return *this;if ( student_ids != NULL)
delete [ ] student_ids;student_ids = new int[rhs.class_size];class_size = rhs.class_size;return *this;
}
think of obj1 = obj2; as being equivalent to obj1.operator=(obj2);
pass the right-hand-side as a referencebut do not allow it to be modified.
returning a reference to the current object allows chain assignments: obj1 = obj2 = obj3;
the this pointer provides access to an object's own address. this is a C++ keyword.
16
operator= and pointers
ClassInfo& operator= (const ClassInfo& rhs) {if ( this == &rhs )
return *this;if ( student_ids != NULL)
delete [ ] student_ids;student_ids = new int[rhs.class_size];class_size = rhs.class_size;return *this;
}
if the right-hand sideand the left-hand sideare identical, (e.g. obj1 = obj1) just returna reference to the current object.(What will happen if we don't check this?)
17
operator= and pointers
Since the current objectwill be assigned a new value, make certain thatany memory already allocated for it isproperly deallocated.
ClassInfo& operator= (const ClassInfo& rhs) {if ( this == &rhs )
return *this;if ( student_ids != NULL)
delete [ ] student_ids;student_ids = new int[rhs.class_size];class_size = rhs.class_size;return *this;
}
18
operator= and pointers
Finally, perform theactual assignment andreturn a reference to the current object.
ClassInfo& operator= (const ClassInfo& rhs) {if ( this == &rhs )
return *this;if ( student_ids != NULL)
delete [ ] student_ids;student_ids = new int[rhs.class_size];class_size = rhs.class_size;return *this;
}
19
pointer data members
Whenever a class has at least one data member that is a pointer, you MUST write a destructor a copy contructor an overloaded assignment operator
THE BIG THREE!
If you need one ofthem, then you alsoneed the other two!
20
friend functions
In many cases, we would like a function to have access to private data members of the class, without the function being a member of the class.
Examples: operator<< needs to print data member values but is not a
class member itself. a function that needs to operate on two or more objects of the
same class e.g. a function that takes as arguments two Points and
computes the distance between them a function that needs to operate on objects of different classes.
e.g. a function HaveCollided() that takes as arguments a Ship and a Torpedo object.
Possible Solution: Use a get method (a.k.a. accessor) that returns the values of
the class data members Use friends!
21
friend functions
A class may allow a function to access its private data members by declaring it as a friend function.
Example: class Torpedo;
class Ship { private: ShipT type; char *name; Coords position; public: ... friend bool HaveCollided(Torpedo& , Ship& );};...bool HaveCollided(Torpedo& t, Ship& s) { ...}
22
friend classes
We may also declare a class A to be a friend of class B. This will give A access to the private members of B. IMPORTANT: This does not mean that B has access to the
private data members of A. In other words, if A is a friend of B, B is not automatically a friend of A.
class CityNetwork {private: City *citylist; Road *highways;public: ...};
class City { private: Coords latitude; Coords longitude; public: ... friend class CityNetwork;
}; Now, CityNetworkcan access latitudeand longitude
23
evil friends?
Friendship may only be granted, not taken.
Keep in mind that a friend function is dependent on the implementation of the class that declared it as a friend. If the implementation changes, the function may need to
be modified and will certainly need to be recompiled. You must always have very good reasons for using
friends.
See also: http://www.parashift.com/c++-faq-lite/friends.html#faq-14.2
24
operator<< as a friend
class ClassInfo {private:
int *student_ids;int class_size;
public: ClassInfo (int size=0);....
friend ostream& operator<< (ostream&, const ClassInfo&)};
ClassInfo::ClassInfo (int size) {....
}
ostream& operator<< (ostream&, const ClassInfo& obj) { ...}
classinfo.h
classinfo.cpp