Upload
ira-burns
View
229
Download
0
Embed Size (px)
Citation preview
EC-241 Object-Oriented Programming
LECTURE 8
PolymorphismOne interface, multiple methodsC++ supports both compile time and runtime
polymorphism
Example Situation That Needs Polymorphism
How to write code that calls the appropriate version of draw() function with same function call? Answer: Polymorphism
Shape class hierarchy
Circle
Right Triangle Isosceles Triangle
Triangle Rectangle
Shape
PolymorphismPolymorphism is a feature of OOP that
enables us to program in “general” rather than in “specific”.
Polymorphism allows us to write programs that process the objects of classes that are part of the same class hierarchy as if they were all objects of the hierarchy’s base class
PolymorphismPolymorphism works with pointersPointers of base class type are used to call
appropriate member functions in objects of several derived classes
This way you need to be concerned with only one type of pointers (i.e. base class pointers only)
Helping feature: Virtual functions (later)
How Polymorphism Works?In the base class, create a virtual function
Size()In the derived classes also, create
appropriate definitions of Size()Create a base class pointer. During execution, if sptr points to a
Rectangle type object, then call to Size() will execute Rectangle’s version of Size().
And if sptr points to a Circle type object, then call to Size() will execute Circle()’s version of Size().
How Polymorphism Works? Shape * sptr;
sptr= new Rectangle(); sptr->Size(); //Rectangle’s Size sptr=new Circle(); sptr->Size(); //Circle’s Size
// Notice the same call being used for different // functionalities// Important: the function Size() has to be virtual in // the base class
#include <iostream>using namespace std;
class Shape{public:
virtual void size(){
cout<<"size of shape\n";}
};
class Circle: public Shape{public:
virtual void size(){cout<<"size of circle\n";}
};class Rectangle: public Shape{public:
virtual void size(){cout<<"size of rectangle\n";}void otherFunction() {cout<<"inside non-inherited function of derived class"; }
};
void main(){
Shape * sptr;sptr= new Circle();sptr->size();sptr=new Rectangle();sptr->size();//following two cases are wrong//case 1:cannot call non-inherited derived class functions through//base class pointer (except by downcasting the pointer)//sptr->otherFunction(); //case 2: cannot assign base class address to derived class pointer//Circle * c;//c= new Shape();
}
Virtual Functions• If size() was not virtual, which version would have
been called?• Answer: Shape’s version• Without virtual functions, the type of the pointer
determines which class’s functionality to invoke.• With virtual function, the type of the object being
pointed to, not the type of the pointer , determines which version of a virtual function to invoke
• Virtual functions are called through base-class pointer handles and base class reference handles, but not through name handles
Constructors and destructorsConstructors cannot be virtual. Why??
Can we have virtual destructors. Why??If a class has virtual functions, provide a
virtual destructor even if one is not required for the class. This ensures that a custom derived-class destructor (if there is one) will be invoked when a derived-class object is deleted via a base class pointer
Dynamic vs. Static Binding• If a program invokes a virtual function
through a base class pointer to a derived class object, the program will choose the correct derived-class function dynamically (i.e. at execution time) based on the object type- not the pointer type.
• Choosing the appropriate function to call at execution time is called dynamic binding (or late binding)
Dynamic vs. Static Binding• When a virtual function is called by
referencing a specific object by name and using the dot operator, the function invocation is resolved at compile time (this is called static binding) and the virtual function that is called is the one defined for (or inherited by) the class of that particular object- this is not polymorphic behavior.
• Thus, dynamic binding with virtual functions occurs only through pointers.
Abstract ClassesA class that cannot be instantiatedRepresents general features of its sub-
classes; thus can act as stereo-typesCan be used as a common interface to a
hierarchy of classes
Abstract ClassesExample
CD player and DVD player Both involve an optical disk Operations
Insert, remove, play, record, and stop such disks
Abstract Classes
CDP and DVDP have an abstract base class GDP
Abstract ClassesA class is made abstract by including at least
one pure virtual functionA pure virtual function does not have an
implementation, and has a =0 in its signature
A subclass of an abstract class is also abstract if it does not provide implementations for all the pure virtual functions in the superclass
A class that has all its member functions pure virtual is called an interface
Abstract Base Class – Example in C++
class Shape // abstract base class{ public: virtual void move(int dx, int dy) =0;// pure
//virtual function virtual void show() const =0; // pure
//virtual function};
Abstract Base Class – Example contd.class Circle : public Shape // concrete class{ int xcenter,ycenter,radius;
public:
Circle(int xc, int yc, int r) : xcenter(xc), ycenter(yc), radius(r) {}
void move(int dx, int dy) { xcenter += dx; ycenter += dy; }
void show() const { cout <<"Circle centered at ("<<xcenter<<","<<ycenter<<") with radius "
<<radius<<"."<<endl; }};
Abstract Base Class – Example contd.class Square : public Shape // concrete class{ int xll,yll,xur,yur;
public:
Square(int x1, int y1, int x2, int y2) : xll(x1), yll(y1), xur(x2), yur(y2) {}
void move(int dx, int dy) { xll += dx; yll += dy; xur += dx; yur += dy; }
void show() const { cout <<"Square with lower left corner at ("<<xll<<","<<yll <<") and upper right corner at ("<<xur<<","<<yur<<")."<<endl;
}
};
Abstract Base Class – Example contd.void main() {// Shape s; // compiler error, Shape is abstract
Circle c(10,20,5); Square s(0,0,15,10); Shape *array[2]={&c,&s}; cout <<"Before move:"<<endl; for (int i=0; i<2; i++) array[i]->show();
for (int i=0; i<2; i++) array[i]->move(5,-5);
cout <<endl<<"After move:"<<endl; for (int i=0; i<2; i++) array[i]->show();}