1 Polymorphism Lesson #7 Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL...

Post on 22-Dec-2015

214 views 0 download

Transcript of 1 Polymorphism Lesson #7 Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL...

1

Polymorphism

Lesson #7

Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL Program. The notes were subsequently revised by M. Deek

2

Content

Definition and Basic Terminology Polymorphism and Dynamic

Binding

3

Polymorphism

Polymorphism is a concept where a single name may denote objects of different classes that are related by some common base class [Booch].

In polymorphic languages some values and variables may have more than one type.

A function is polymorphic if it may be applied to arguments of different types.

Polymorphism (poly = many and morph = states or forms, etc.)

4

Polymorphism and Overloading

Realized by using a set of monomorphic functions. Different code is used for different types.

Overloading means that the same operation is implemented through different methods with the same function name. For different types, different implementations (methods) of the same operation are executed.

5

Polymorphism and Overloading

Coercion is explicitly converting types (such as integer to real). An example of coercion is casting in C or C++.

6

Static and Dynamic Binding

When a reference to a member function is resolved at compile time, then static binding is used.

When a reference to a member function can only be resolved at run-time, then this is called dynamic binding.

7

Polymorphism and Dynamic Binding

To implement polymorphism, the programming language must support dynamic binding. Polymorphism----- a concept Dynamic binding -----implementation

8

Polymorphism and Dynamic Binding

Classical paradigm function open_disk_file() function open_tape_file() function open_diskette_file()

Object-Oriented paradigm Function My_File.open_file()

9

Polymorphism and Dynamic Binding

All that is needed is myFile.open() Correct method invoked at run-time

(dynamically). Method open can be applied to objects of

different classes. Polymorphism

10

Polymorphism in C++

Virtual functions and polymorphism

Abstract and Concrete classes

11

Polymorphism in C++

The ability to manipulate instances of derived class through a set of operations defined in their base class.

Each derived class can implement the operations defined in the base class differently, while retaining a common class interface provided by the base class.

12

Polymorphism in C++

Virtual Function A non-static member function prefaced

by the virtual specifier. It tells the compiler to generate code that

selects the appropriate version of this function at run-time.

13

Example#include <iostream.h>class Employee {public: void Display(); // non-virtual virtual void CalcPaycheck(); // virtual};class SalariedEmployee :public Employee {public: void Display(); virtual void CalcPaycheck();};void Employee::CalcPaycheck(){cout << "Employee"<<"\n";}

14

Example

void SalariedEmployee::CalcPaycheck()

{cout << "SalariedEmployee"<<"\n";}

void Employee::Display()

{ CalcPaycheck(); }

void SalariedEmployee::Display()

{ CalcPaycheck();}

int main()

{ Employee * ep = new SalariedEmployee;

//...

ep->Display();

return 0;

}//ex7salemp.cpp, Result: SalariedEmployee

15

Common Interface#include <iostream.h>

class Employee {

public:

long GetDepartment() const{return deptNum;};

long GetId() const{return id;};

void SetDepartment( long deptId ){};

void SetId(){};

virtual void CalcPaycheck() =0;

virtual void Input(){};

private:

long id;

long deptNum;

};

16

Common Interface

class SalariedEmployee :public Employee {public: Void CalcPaycheck(){cout<<"SalariedEmployee"<<endl;}; class HourlyEmployee :public Employee {public: void CalcPaycheck(){cout<<"HourlyEmployee"<<endl;}; void ProcessAnyEmployee( Employee & er ) { long anId = er.GetId(); // non-virtual er.CalcPaycheck(); // virtual } void main() {SalariedEmployee S; HourlyEmployee H; ProcessAnyEmployee( S ); ProcessAnyEmployee( H ); }

17

18

Virtual Destructors

Calling the wrong destructor could be disastrous, particularly if it contains a delete statement.

Destructors are not inherited. One must be defined for each derived class.

Constructors are not inherited.

19

Virtual Destructors

#include <iostream.h>

class Item {

public:

Item(){id = 0;};

virtual ~Item(){ cout <<"Item deleted"<<endl;};

private:

int id;

};//ex7virdes.cpp

20

Virtual Destructors

class BookItem: public Item { public:

BookItem(){title = new char [50];}; virtual ~BookItem(){delete title;

cout <<"BookItem deleted"<<endl;}; private:

char * title;}; void main(){ Item * p;

p = new BookItem; delete p;

}

21

22

23

Stop Retry Ignore

24

Abstract Classes An abstract class is a class that can

only be a base class for other classes.

Abstract classes represent concepts for which objects cannot exist.

A class that has no instances is an abstract class.

Concrete classes are used to instantiate objects.

25

An Abstract Class

In C++, a class that has one or more virtual functions is an abstract class.

An abstract class either contains or inherits at least one pure virtual function.

A pure virtual function is a virtual function that contains a pure-specifier, designated by the “=0”.

26

Example:

Shape

Circle Polygon

27

The Class Shape

#include <iostream.h>

class Point {

};

class Shape {

public:

virtual ~Shape(){};

virtual void Draw() const = 0;

virtual void MoveTo( int x2, int y2 ) = 0;

virtual void Rotate( int degrees ) = 0;

};

28

class Circle :public Shape {public:

Circle(){};Circle( const Point & aCenter, float aRadius ){};

virtual ~Circle(){}; virtual void Draw() const{cout<<"Drawing!"<<endl;}; virtual void MoveTo( int x2, int y2)

{cout<<"MoveTo"<<endl;}; virtual void Rotate( int degrees)

{cout<<"Rotate!"<<endl;};private: Point center; float radius;};

Shape

29

Shape

class Polygon :public Shape {public: Polygon(); Polygon( Point & cent, Point * verts ); virtual ~Polygon();private: Point center; Point * vertices; // array of Points};

30

Shape

int main()

{ Circle C;

C.Draw();

Point center;

Point vertices[10];

//Cannot create instance of abstract class Polygon:

// Polygon P( center, vertices );

return 0;

}

31

32

33

34

An Abstract Derived Class

If a pure virtual function is not defined in a derived class, the derived class is also considered an abstract class.

When a derived class does not provide an implementation of a virtual function the base class implementation is used.

It is possible to declare pointer variables to abstract classes.

35

Example:Package Shipping

The input file includes record in the following format: Tracking number, organization Zip code,

destination Zip code,shipping date, cost, and weight .

For example: 100101 31313 33130 960402 15.00 8.0

36

Package Shipping

The output file should be in the following format:

0: [100101,31313,33130,960402,15.00,8.00]

1: [102001,20000,96535,960403,7.50,4.50]

2: [100311,10101,12110,960405,5.00,3.00]

3: [101400,10000,70515,960410,5.30,3.20]

4: [110510,22222,33133,960412,15.00,10.50]

Total weight of 5 packages = 29.2

37

Package Shipping

The table should be sorted in ascending order

Packages sorted by tracking number......

0: [100101,31313,33130,960402,15.00,8.00]

1: [100311,10101,12110,960405,5.00,3.00]

2: [101400,10000,70515,960410,5.30,3.20]

3: [102001,20000,96535,960403,7.50,4.50]

4: [110510,22222,33133,960412,15.00,10.50]

38

Package Shipping

The user enters a tracking number, then the program searches and displays the index and the detail of the package:

Searching for package 101400Found at position 2...........................Tracking number: 101400Origination zip code: 10000Destination zip code: 70515Date sent: 960410Shipment cost: 5.30Package weight 3.20

39

The Design

Item

Package

Table

TableAsArray

40

Item.h#include <iostream.h> class Item {public: virtual ~Item() { } virtual int Compare( const Item & I2 ) const = 0;friend ostream & operator <<( ostream & os, const Item

& I ); friend istream & operator >>( istream & inp, Item & I );private: virtual void printOn( ostream & os ) const = 0; virtual void readFrom( istream & inp ) = 0;};

41

Package.h #include <iostream.h> #include "item.h" class Package :public Item { public: Package(); Package( long trackNumP, long originP, long destinP, long dateP, float costP, float weightP ); long GetDestination() const; long GetTrackingNumber() const;

42

Package.h float GetWeight() const; void PrintLong( ostream & os ) const; int Compare( const Item & I2 ) const; void SetTrackNum( long trackNumP ); void SetOrigin( long originP ); void SetDestination( long destinP ); void SetDate( long dateP ); void SetCost( float costP ); void SetWeight( float weightP ); void Init();

43

Package.h

private: long trackNum; // tracking number long origin; // originating zip code long destin; // destination zip code long date; // date sent (yymmdd) float cost; // shipping cost float weight; // weight in kilograms virtual void printOn( ostream & os ) const; virtual void readFrom( istream & is ); };

44

Table.h #include "item.h" #include "limits.h" class Table { public: virtual ~Table() { } virtual void AddItem( Item * I ) = 0; virtual void Clear() = 0; virtual unsigned GetCount() const = 0; virtual Item * GetItemPtr( unsigned i ) const = 0; virtual unsigned IndexOf( const Item * P ) const = 0; virtual void Sort() = 0;// Ascending order };

45

Tablearr.h #include <iostream.h> #include <iomanip.h> #include <assert.h> #include "table.h" class TableAsArray : public Table { public: TableAsArray( unsigned tableSize ); virtual ~TableAsArray(); virtual void AddItem( Item * I ); virtual void Clear(); virtual unsigned GetCount() const; virtual Item * GetItemPtr( unsigned i ) const; virtual unsigned IndexOf( const Item * P ) const; virtual void Sort();

46

Tablearr.h

friend ostream & operator <<( ostream & os, const TableAsArray & T ); private: Item ** data; // array of pointers to Items unsigned size; // allocation size unsigned count; // number of Items private: void swap( Item * & p1, Item * & p2 ); };

47

Tablearr.h inline TableAsArray::~TableAsArray() { Clear(); } inline unsigned TableAsArray::GetCount() const { return count; } inline Item * TableAsArray::GetItemPtr( unsigned i )

const { assert( i < count ); return data[i]; }

48

Item.cpp

#include "item.h"

ostream & operator <<( ostream & os, const Item & I )

{ I.printOn( os );

return os;

}

istream & operator >>( istream & inp, Item & I )

{ I.readFrom( inp );

return inp;

}

49

Package.cpp#include "package.h"

Package::Package()

{ Init();}

Package::Package( long trackNumP, long originP,

long destinP, long dateP, float costP, float weightP )

{ SetTrackNum( trackNumP );

SetOrigin( originP );

SetDestination( destinP );

SetDate( dateP );

SetCost( costP );

SetWeight( weightP );

}

50

Package.cppvoid Package::Init(){ SetTrackNum( 0 ); SetOrigin( 0 ); SetDestination( 0 ); SetDate( 0 ); SetCost( 0.0f ); SetWeight( 0.0f );}long Package::GetDestination() const{ return destin;}long Package::GetTrackingNumber() const{ return trackNum;}float Package::GetWeight() const{ return weight;}

51

Package.cppvoid Package::SetTrackNum( long trackNumP ){ trackNum = trackNumP;}void Package::SetOrigin( long originP ){ origin = originP;}void Package::SetDestination( long destinP ){ destin = destinP;}void Package::SetDate( long dateP ){ date = dateP;}void Package::SetCost( float costP ){ cost = costP;}void Package::SetWeight( float weightP ){ weight = weightP;}

52

Package.cppvoid Package::printOn( ostream & os ) const{ // Save the current flags and precision before modifying them. unsigned svflags = os.setf( ios::showpoint | ios::fixed ); int svprecision = os.precision(2); os << '[' << trackNum << ',' << origin << ',' << destin << ',' << date << ',' << cost << ',' << weight << "]" << endl; // Restore the previous flags and precision. os.precision( svprecision ); os.flags( svflags );}

53

Package.cppvoid Package::PrintLong( ostream & os ) const{ // Save the current flags and precision before modifying them. unsigned svflags = os.setf( ios::showpoint | ios::fixed ); int svprecision = os.precision(2); os << "...........................\n" << "Tracking number: " << trackNum << '\n' << "Origination zip code: " << origin << '\n' << "Destination zip code: " << destin << '\n' << "Date sent: " << date << '\n' << "Shipment cost: " << cost << '\n' << "Package weight " << weight << endl; // Restore the previous flags and precision. os.precision( svprecision ); os.flags( svflags );}

54

Package.cppvoid Package::readFrom( istream & inp ){ Init(); inp >> trackNum >> origin >> destin >> date >> cost >> weight; inp.ignore( 10, '\n');}int Package::Compare( const Item & I2 ) const{ if( trackNum < ((Package &)I2).trackNum ) return -1; else if( trackNum == ((Package &)I2).trackNum ) return 0; else // if( trackNum > ((Package &)I2).trackNum ) return 1;}

55

Tablearr.cpp

// TABLEARR.CPP - TableAsArray class implementation

#include "tablearr.h"

// Create a table of size (sz). Make sure that

// sz is less than UINT_MAX.

TableAsArray::TableAsArray( unsigned sz )

{ size = sz;

assert( size < UINT_MAX );

count = 0;

data = new Item *[size];

for(unsigned j = 0; j < size; j++)

data[j] = 0;

}

56

Tablearr.cpp

// Add an item to the table. P cannot be pointer to const

// because data[] does not contain pointers to constants.

void TableAsArray::AddItem( Item * P )

{ if( count < size )

data[count++] = P;

else

cout << "Error: Table full; item not added.\n";

}

57

Tablearr.cpp

// Empty the table: delete all objects pointed to

// by the array and delete the array of pointers.

void TableAsArray::Clear()

{ for(unsigned i = 0; i < count; i++)

delete data[i];

delete [] data;

count = 0;

size = 0;

}

58

Tablearr.cpp

ostream & operator <<( ostream & os, const TableAsArray & T ){ for(unsigned i = 0; i < T.count; i++) os << setw(3) << i << ": " << *T.data[i] << endl; return os;}// Attempt to locate item P in the table. If successful,// return its index position; otherwise, return UINT_MAX,// a standard constant defined in limits.h.unsigned TableAsArray::IndexOf( const Item * P ) const{ for(unsigned i = 0; i < count; i++) if( P->Compare( *data[i]) == 0 ) return i; return UINT_MAX;}

59

Tablearr.cpp

// Sort the table using a Selection sort.

void TableAsArray::Sort()

{ for(unsigned curr = 0; curr < count-1; curr++)

{ unsigned minIndex = curr;

for(unsigned k = curr+1; k < count; k++)

if( data[k]->Compare(*data[minIndex]) < 0 )

minIndex = k;

if( minIndex != curr )

swap( data[curr], data[minIndex] );

}

}

60

Tablearr.cpp

void TableAsArray::swap( Item * & p1, Item * & p2 )

{ Item * temp;

temp = p1;

p1 = p2;

p2 = temp;

}

61

Shipping.cpp

// SHIPPING.CPP - Main Package Shipping Service program. #include <stdlib.h> #include <iostream.h> #include <fstream.h> #include "package.h" #include "tablearr.h" int main() {// Open input file, get number of Packages, // open output file, create table: ifstream input( "PACKAGES.TXT" ); if( !input ) { cout << "Input file not found; halting program.\n"; abort(); }

62

Shipping.cpp

ofstream outfile( "OUTFILE.TXT" );

unsigned numRecords;

input >> numRecords;

input.ignore( 1, '\n' );

if( numRecords < 1 )

{

cout << "Package file is empty. Ending program.\n";

return 0;

}

63

Shipping.cpp

// Read all Packages from the input file, add them to the table and //display the table:

TableAsArray ptable( numRecords );Package * pkg;unsigned i;for(i = 0; i < numRecords; i++){ pkg = new Package; input >> *pkg; ptable.AddItem( pkg ); if( input.eof() ) break;}

64

Shipping.cpp

outfile << ptable << endl; // output the table

// Get each Package from the table, add its

// weight to a total, and display the total

// weight of all packages.

Package * z;

float sum = 0.0;

for(i = 0; i < ptable.GetCount(); i++)

{ z = (Package *)ptable.GetItemPtr( i );

sum += z->GetWeight();

}

outfile << "Total weight of packages = "

<< sum << "\n\n";

65

Shipping.cpp// Sort and display the table.ptable.Sort();outfile << "Packages sorted by tracking number......\n" << ptable << '\n';// Search for a particular package by its tracking// number. If found, retrieve and display the package.//long id = 101400L;long id;cout << "Input the id you would like to search:";cin>> id;pkg->Init();pkg->SetTrackNum( id );unsigned n = ptable.IndexOf( pkg );

66

Shipping.cpp

outfile << "Searching for package " << id << '\n';if( n != UINT_MAX ){ outfile << "Found at position " << n << '\n'; pkg = (Package *)ptable.GetItemPtr( n ); pkg->PrintLong( outfile );}else outfile << "Package " << id << " not found.\n";// When ptable goes out of scope, its destructor deallocates// all Package objects stored in the table. return 0;}//cis601source/ch08/shipping/shipping.cpp

67

68

Packages.txt

5 100101 31313 33130 960402 15.00 8.0 102001 20000 96535 960403 7.50 4.5 100311 10101 12110 960405 5.00 3.0 101400 10000 70515 960410 5.30 3.2 110510 22222 33133 960412 15.00 10.5

69

Outfile.txt 0: [100101,31313,33130,960402,15.00,8.00] 1: [102001,20000,96535,960403,7.50,4.50] 2: [100311,10101,12110,960405,5.00,3.00] 3: [101400,10000,70515,960410,5.30,3.20] 4: [110510,22222,33133,960412,15.00,10.50]Total weight of packages = 29.2Packages sorted by tracking number...... 0: [100101,31313,33130,960402,15.00,8.00] 1: [100311,10101,12110,960405,5.00,3.00] 2: [101400,10000,70515,960410,5.30,3.20] 3: [102001,20000,96535,960403,7.50,4.50] 4: [110510,22222,33133,960412,15.00,10.50]

70

Outfile.txt (cont’d)

Searching for package 101400

Found at position 2

...........................

Tracking number: 101400

Origination zip code: 10000

Destination zip code: 70515

Date sent: 960410

Shipment cost: 5.30

Package weight 3.20

71

Supplement

this : Within a member function of a class,

“this” is the name of an implicit pointer to the current object which receives the message relevant to this function.

“this” is really a polymorphic word which can mean any object in the C++ language.

72

thisPoint & Point::Set(int valX,int valY) {

x=valX;

y=valY;

return *this;

};

main()

{ Point P, P2;

P.SetX(300);

cout <<"P.x="<< P.GetX()<<"\n";

cout <<"P2.x="<< P2.Set(400, 500).GetX()<<"\n";

}//ex7thispoint.cpp

73

74

75

“this” in the base classclass ColorPoint: public Point{

public:int getColor() {return color;};void setColor(int c) {color=c;};

private:int color;

}; void main() { Point P1;

ColorPoint CP;CP.setColor(125);cout <<"P1.x="<< P1.Set(400, 500).GetX()<<"\n";cout <<"CP.x="<< CP.Set(800, 300).GetX() <<" CP.color = "<<CP.getColor()<<"\n";

}//ex7thisinh.cpp

76

77

78

Implicit “this”

According to object-oriented methodology, functions should be invoked by messages.

For example, there are functions (defined in the class) called in the class definition (the implementation). fun(); Who is the receiver? It’s certainly *this.

In fact, it is the same as: this->fun();

79

Example

class clsthis{int i;

void add(int x){i = i + x;}; // this->i = this->i +x; public: void init(int val){i = val;};// this->i = val;

int get(){ add(50); //this ->add(50); return i;};// return this->i;

} main(){clsthis cls;int k, j; cls.init(20); k = cls.get(); cout << k<<endl;}//ex7this.cpp

80

81

82

Readings

Reading: Chapter 8 Sections 8.1 - 8.2