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 .
30
Embed
Understanding Polymorphism tMyn1 Understanding Polymorphism Polymorphism requires the use of derived classes. It always involves the use of a pointer to.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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.
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…:
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;
};
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;}
Carton::Carton(){ cout<<"Derived class constructor, object ”
<<this<<endl;cout<<"Weight: ";
cin>>weight;cin.get();
}Carton::~Carton(){ cout<<"Derived class destructor, object ”
<<this<<endl;}
Understanding Polymorphism
tMyn 7
int main(array<System::String ^> ^args){
Carton* fourth=new Carton(); delete fourth;
Box* fifth=new Carton(); delete fifth; return 0;}
Understanding Polymorphism
tMyn 8
The derived class destructor will never be called!
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.
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:
• 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.
Understanding Polymorphism
tMyn 20
• What if we call the calcVol() function for the Carton object directly?:
<<"The volume is "<<pBox->calcVol()<<endl; return 0;}
Understanding Polymorphism
tMyn 25
Did not work!
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:
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();
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.
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.
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.