1 overloading overloading allows a function or operator to have a different meaning depending on the...

24
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

Upload: roger-king

Post on 13-Jan-2016

219 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: 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+

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

Page 2: 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+

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.

Page 3: 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+

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

Page 4: 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+

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.

Page 5: 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+

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

Page 6: 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+

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

Page 7: 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+

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

Page 8: 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+

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.

Page 9: 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+

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?

Page 10: 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+

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

Page 11: 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+

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;}

Page 12: 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+

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;

...

Page 13: 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+

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

Page 14: 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+

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!

Page 15: 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+

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.

Page 16: 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+

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?)

Page 17: 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+

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;

}

Page 18: 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+

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;

}

Page 19: 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+

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!

Page 20: 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+

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!

Page 21: 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+

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) { ...}

Page 22: 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+

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

Page 23: 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+

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

Page 24: 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+

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