understanding polymorphism tmyn1 understanding polymorphism polymorphism requires the use of derived...

30
Understanding Po lymorphism tMyn 1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to an object or a reference to an object. Polymorphism only operates within a class hierarchy, so the ability to derive one class from another is fundamental to making polymorphism possible. The first step is the need to understand the role of a pointer to a base class .

Upload: stephany-rose

Post on 18-Jan-2016

226 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 1

Understanding Polymorphism

• Polymorphism requires the use of derived classes.• It always involves the use of a pointer to an object or

a reference to an object.• Polymorphism only operates within a class hierarchy,

so the ability to derive one class from another is fundamental to making polymorphism possible.

• The first step is the need to understand the role of a pointer to a base class.

Page 2: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 2

• The objects of a derived class represent a subset of objects of the base class – in other words, every derived class object is also a base class object.

• Consequently, you can always use a pointer to base class to store the address of a derived class object – in fact, you can even use a pointer to an indirect base class for this purpose.

• REMEMBER, however, that a problem arises, though, when you want to destroy objects through a base class pointer – and this will be addressed later on…:

Page 3: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 3

#include "stdafx.h"#include <iostream>

using namespace System;using namespace std;

class Box{public:

Box(); ~Box();

double volume();private: double length;

double breadth; double height;

};

Page 4: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 4

Box::Box(){ cout<<"Base class constructor, object "<<this<<endl;

cout<<"Length: "; cin>>length;

cin.get();cout<<"Breadth: ";

cin>>breadth;cin.get();cout<<"Height: ";

cin>>height;cin.get();

}Box::~Box(){ cout<<"Base class destructor, object "<<this<<endl;}

Page 5: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 5

double Box::volume(){

return length*breadth*height;}class Carton:public Box{public: Carton(); ~Carton();private: double weight;};

Page 6: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 6

Carton::Carton(){ cout<<"Derived class constructor, object ”

<<this<<endl;cout<<"Weight: ";

cin>>weight;cin.get();

}Carton::~Carton(){ cout<<"Derived class destructor, object ”

<<this<<endl;}

Page 7: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 7

int main(array<System::String ^> ^args){

Carton* fourth=new Carton(); delete fourth;

Box* fifth=new Carton(); delete fifth; return 0;}

Page 8: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 8

The derived class destructor will never be called!

Page 9: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 9

• Even if you can use a pointer to base to store the address of a derived class object, the reverse of this is not true.

• This is logical, because the base classes do not describe a complete derived class object.

• A derived class object always contains a complete sub-object of each of its bases, but each base class only represents a part of a derived class object.

• Let’s start with an example that is not a satisfactory one. The aim of the next example is to look more closely at the behaviour of inherited member functions and the relationship that they have with derived class member functions.

Page 10: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 10

• First we revise the Box class to include a function that calculates the volume (double calcVol()) of a Box object and another function that displays the resulting volume (void displayVol()).

• As a second step we define a different calculate volume -function in the derived class (double calcVol()).

• The idea here is that we can (??) get the inherited function displayVol() to call the derived class version of the function calcVol() when we call it for an object of the Carton class:

Page 11: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 11

#include "stdafx.h"#include <iostream>#include <string>using namespace System;using namespace std;

class Box{public:

Box(); Box(double, double, double); ~Box(); void displayVol(); double calcVol();

protected: double length; double breadth; double height;};

Page 12: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 12

Box::Box(){

cout<<"Base class default constr., object ” <<this<<endl;cout<<"Length: ";

cin>>length;cin.get();cout<<"Breadth: ";

cin>>breadth;cin.get();cout<<"Height: ";

cin>>height;cin.get();

}

Page 13: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 13

Box::Box(double lv, double bv, double hv){

cout<<"Base class constructor with 3 params., object ”<<this<<endl;

length=lv; breadth=bv; height=hv;

}Box::~Box(){ cout<<"Base class destructor, object "<<this<<endl;}void Box::displayVol(){ cout<<"Usable volume is "<<calcVol()<<endl;}

Page 14: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 14

double Box::calcVol(){

return length*breadth*height;}class Carton:public Box{public:

Carton(); Carton(string); Carton(double, double, double, string); ~Carton(); double calcVol();private: string* text;};

Page 15: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 15

Carton::Carton():Box(){ cout<<"Derived class default constr., object ”

<<this<<endl;text=new string;cout<<"Typical usage: ";

getline(cin, *text);}Carton::Carton(string message):Box(){ cout<<"Derived class constructor with 2 params, object "

<<this<<endl; text=new string;

*text=message;}

Page 16: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 16

Carton::Carton(double lVal, double bVal, double hVal, string message):Box(lVal, bVal, hVal){

cout<<"Derived class constructor with 4 params., object ” <<this<<endl;

text=new string; *text=message;

}Carton::~Carton(){ cout<<"Derived class destructor, object "<<this<<endl; delete text; text=0;}

Page 17: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 17

Carton::~Carton(){

cout<<"Derived class destructor, object "<<this<<endl; delete text; text=0;}double Carton::calcVol(){ return 0.85*length*breadth*height;}int main(array<System::String ^> ^args){

Box first=Box(); first.displayVol(); Carton second=Carton(); second.displayVol(); return 0;}

Page 18: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 18

The output is rather disappointing:

Page 19: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 19

• The trouble is that in this program, when the calcVol() function is called by the displayVol() function, the compiler sets it once and for all as the version of calcVol() defined in the base class.

• No matter how you call displayVol(), it will never call the Carton version of the calcVol() function.

• When function calls are fixed in this way, before the program is executed, it is called static resolution of the function call or static binding.

• The term early binding is also commonly used.• A particular calcVol() function is bound to the call

from the function displayVol() during the compilation of the program.

Page 20: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 20

• What if we call the calcVol() function for the Carton object directly?:

Page 21: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 21

int main(array<System::String ^> ^args){

Box first=Box(); first.displayVol(); Carton second=Carton(); second.displayVol();

cout<<"New try:"<<endl <<"The volume is "<<second.calcVol()<<endl;

return 0;}

Page 22: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 22

That worked.. and the call was resolved statically!

Page 23: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 23

• Next try: let’s add the statement to call the calcVol()- function through a pointer to the base class:

Page 24: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 24

int main(array<System::String ^> ^args){

Box first=Box(); first.displayVol(); Carton second=Carton(); second.displayVol();

Box* pBox=&second; cout<<"Next try: "<<endl

<<"The volume is "<<pBox->calcVol()<<endl; return 0;}

Page 25: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 25

Did not work!

Page 26: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 26

• As a summary:• A call to calcVol() for the derived class object,

second, calls the derived class calcVol() function, which was what we wanted.

• The call through the base class pointer pBox, however, is resolved to the base class version of calcVol(), even though pBox contains the address of the object second.

• In other words, both calls are resolved statically.• The compiler will implement these calls as:

Page 27: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 27

cout<<"New try: "<<endl <<“The volume is “ <<second.Carton:: calcVol();

and:

cout<<“Next try: "<<endl <<“The volume is “

<<pBox->Box:: calcVol();

Page 28: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 28

• A static call of a function through a pointer is determined solely by the type of the pointer, and not by the object to which it points.

• The pointer pBox is of type pointer to Box, so any static call using pBox can only call a function member of Box.

• In other words: any call to a function through a base class pointer that is resolved statically will call a base class function.

Page 29: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 29

• How should the program work?• If we call displayVol() with a derived class object, we

would like it to determine that the derived class calcVol() function should be called, not the base class version.

• Similarly, if we call the calcVol() function through a base class pointer, then we want it to choose the calcVol() function that is appropriate to the object pointed to.

• This sort of operation is referred to as dynamic binding or late binding.

• In order to achieve our aims we need to specify that calcVol() is a virtual function.

Page 30: Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to

Understanding Polymorphism

tMyn 30

• When you declare a function as virtual in a base class, you indicate to the compiler that you want dynamic binding for the function in any class that’s derived from this base class.