COEN244: Polymorphism
Aishy Amer
Electrical & Computer Engineering
Polymorphism means “variable behavior”/“ability to appear in many forms”
OutlineCasting between objects
Using pointers to access objects
Static polymorphism: compile-time type andfunction checking
Dynamic polymorphism: run-time type andfunction checking
Virtual functions: can be over-ridden at run
time
Pure Virtual functions: must be over-ridden
Abstract Classes: classes with at least onepure virtual function
Virtual destructor
c© A. Amer Polymorphism 1
Casting
Casting: conversion from one data type to another typec o n v e r t t o t y p e ( express ion ) ;// Example :t = i n t ( x ) ; q=double ( y ) ;
c© A. Amer Polymorphism 2
Casting
Casting: conversion from one data type to another typec o n v e r t t o t y p e ( express ion ) ;// Example :t = i n t ( x ) ; q=double ( y ) ;
Standard numerical conversions are used forintegral promotions (e.g., enum to int)integral conversions (e.g., int to unsigned int)floating point conversions (e.g., float to double)floating-integral conversions (e.g., int to float)arithmetic conversions(e.g., converting operands to the type of the widestoperand before evaluation)
c© A. Amer Polymorphism 2
Casting
Implicit conversions:
Some conversions are performed automatically by thecompiler without intervention by the programmerStandard C++ conversions and user-defined conversionsare performed implicitly by the compiler where neededExamples?
Explicit conversions:
Conversions which must be explicitly specified by theprogrammer
c© A. Amer Polymorphism 3
C++ explicit casting operators
static cast: convert one type to another type
can be used to reverse any of the implicit conversions(e.g., int to float)rely on static (compile-time) type informationfast and safe
c© A. Amer Polymorphism 4
C++ explicit casting operators
static cast: convert one type to another type
can be used to reverse any of the implicit conversions(e.g., int to float)rely on static (compile-time) type informationfast and safe
dynamic cast: careful, type-sensitive casting at run time
for safe navigation of an inheritance hierarchy
reinterpret cast: type conversions on un-related types
produces something that has the same bit pattern as theoriginal
const cast : (UNSAFE!!)cast away the “const-ness” or “volatility” of a type
c© A. Amer Polymorphism 4
C++ explicit casting operators
All casting operators have the same syntax:stat ic_cast conver t_ to_type ( expr ) ;/ / ==> Convert expr to type conver t_ to_typestat ic_cast <DerivedClass ∗> ( PointerToBaseObj )
Use the least dangerous (most specific) casting alternative
c© A. Amer Polymorphism 5
C++ casting: examples
const i n t x =5;const i n t ∗ pX ; / / changeable p o i n t e r to constant i n t∗pX = 3; / / i l l e g a l − can ’ t use pX to modify an i n tpX = &someOtherIntVar ; / / l e g a l − pX can po in t somewhere e lse
i n t ∗ const pY ; / / constant p o i n t e r to changeable i n t∗pY = 4; / / l e g a l − can use pY to modify an i n tpY = &someOtherIntVar ; / / i l l e g a l − can ’ t make pY po in t anywhere e lse
const i n t ∗ const pZ ; / / const p o i n t e r to const i n t∗pZ = 5; / / i l l e g a l − can ’ t use pZ to modify an i n tpZ = &someOtherIntVar ; / / i l l e g a l − can ’ t make pZ po in t anywhere e lse
class Person {public :
/ / r e t u r n a const char∗ const ==> can ’ t change the p o i n t e r to po in t/ / somewhere else , and you can ’ t modify what the p o i n t e r po in t s toconst char∗ const GetName ( ) { return m_szName; } ;. . .c© A. Amer Polymorphism 6
C++ casting: examples
i n t x = 37; i n t y = 8;
double q = x / y ; / / c l a s s i c mistake , r e s u l t i s rounded to an i n tcout << q ; / / p r i n t s " 4.000000"double q = ( double ) x / y ; / / cast r e s u l t as double so i t ’ s not roundedcout << q ; / / p r i n t s "4.625000"
/ / Bas cas t ing : fo rce the compi ler to put the address o f/ / a const i n t v a r i a b l e i n t o a normal i n t ∗const i n t x = 4; / / x i s const , i t can ’ t be modi f iedconst i n t ∗ pX = &x ; / / you can ’ t modify x through the pX p o i n t e rcout << x << endl ; / / p r i n t s "4 "
i n t ∗ pX2 = ( i n t ∗ )pX ; / / e x p l i c i t l y cast pX as an i n t ∗∗pX2 = 3; / / r e s u l t i s undef ined
cout << x << endl ; / / who knows what i t p r i n t s ?/ / The code compiles and runs w i thou t crashing , but who knows what i s x
c© A. Amer Polymorphism 7
C++ casting: examples
/ / The Const_cast Operatorconst i n t x = 4; / / x i s const , i t can ’ t be modi f iedconst i n t ∗ pX = &x ; / / you can ’ t modify x through the pX p o i n t e r
cout << x << endl ; / / p r i n t s "4 "
i n t ∗ pX2 = const_cast < i n t ∗ > (pX ) ; / / e x p l i c i t l y cast pX as non−const
∗pX2 = 3; / / r e s u l t i s undef inedcout << x << endl ; / / who knows what i t p r i n t s ?
/ / With const_cast : change the const−ness of a va r iab le , and never i t s type
c© A. Amer Polymorphism 8
Object casting
Object casting:
conversion of the type of an object to that of another type
s t a t i c c a s t <DerivedClass ∗> ( PointerToBaseObj )/ / Examplec i r c l e P t r = s t a t i c c a s t < C i r c l e ∗ >( p o i n t P t r ) ;
An object of a publicly derived class can also be treated asan object of its base class
c© A. Amer Polymorphism 9
Object casting
Object casting:
conversion of the type of an object to that of another type
s t a t i c c a s t <DerivedClass ∗> ( PointerToBaseObj )/ / Examplec i r c l e P t r = s t a t i c c a s t < C i r c l e ∗ >( p o i n t P t r ) ;
An object of a publicly derived class can also be treated asan object of its base class
A base class object cannot automatically be treated as aderived class object!
We can use an explicit castto convert a base-class pointer to a derived-class pointer
Results of such conversion cannot be guaranteed ingeneral
c© A. Amer Polymorphism 9
Object casting
Object casting is used forpointer conversion(e.g., derived class pointer to base class pointer)reference conversion(e.g., derived class reference to base class reference)pointer-to-member conversion(e.g., from pointer to member of a base class to pointer tomember of a derived class)
A conversion from type SS to TT can ONLY be done if
the conversion from type TT to SS is an implicit conversion
c© A. Amer Polymorphism 10
Object pointer casting: static_cast
static_cast: no run-time type checking
Down-casting:convert a base class pointer to a derived class pointeronly if the conversion is unambiguous(& base class is non-polymorphic)
c© A. Amer Polymorphism 11
Object pointer casting: static_cast
static_cast: no run-time type checking
Down-casting:convert a base class pointer to a derived class pointeronly if the conversion is unambiguous(& base class is non-polymorphic)
Example:c l a s s BankAcct { . . . } ;c l a s s SavingsAcct : public BankAcct { . . . } ;
/ / Given a b a s e c l a s s p o i n t e r ,/ / we can c a s t i t t o a d e r i v e d c l a s s p o i n t e r :void foo ( BankAcct∗ a c c t ) {SavingsAcct∗ d1 = s t a t i c c a s t <SavingsAcct∗> ( a c c t ) ;}
c© A. Amer Polymorphism 11
Object pointer casting: static_cast
static cast : no run-time type checking→ if acct does not refer to an actual SavingsAcctthen the result of the cast is undefined
c© A. Amer Polymorphism 12
Object pointer casting: static_cast
static cast : no run-time type checking→ if acct does not refer to an actual SavingsAcctthen the result of the cast is undefined
Applied to pointers to objects:Cast a pointer of a derived class to its base classCast a pointer of a base class to its derived class• The base class that is being casted is not checked to
determine whether this is a complete class of thedestination type or not:
c l a s s Base { . . . } ;c l a s s Derived : public Base { . . . } ;Base ∗ a = new Base ;Derived ∗ b = s t a t i c c a s t <Derived∗> ( a ) ;
c© A. Amer Polymorphism 12
static_cast examples
Circle is derived from Point:class Poin t {
f r iend ostream& operator <<(ostream&, Po in t & ) ;public :
Po in t ( i n t = 0 , i n t = 0 ) ;void se tPo in t ( int , i n t ) ; / / access only base par t si n t getX ( ) const { return x } ;
protected :i n t x ; i n t y ;
} ;
/ / Const ruc torPoin t : : Po in t ( i n t a , i n t b ) { se tPo in t ( a , b ) ; }
c© A. Amer Polymorphism 13
static_cast examples
const double PI = 3.14159;
class C i r c l e : public Poin t {f r iend ostream& operator <<(ostream&, C i r c l e &) ;public :
C i r c l e ( f l o a t = 0.0 , i n t = 0 , i n t = 0 ) ;void setRadius ( f l o a t ) ; / / access der i ve par t s on lyi n t getRadius ( ) const { return r ; }f l o a t area ( ) const { return PI∗ r ∗ r ; }protected :
f l o a t r ;} ;
C i r c l e : : C i r c l e ( f l o a t rad , i n t a , i n t b ) : Po in t ( a , b ) { setRadius ( rad ) ; }
c© A. Amer Polymorphism 14
static_cast examples
/ / Normal UsePoin t p (4 , 5 ) , ∗ p o i n t P t r ;C i r c l e c (0 .707 , 1 , 2 ) , ∗ c i r c l e P t r ;
/ / Assign po in te r s normal lyp o i n t P t r = &p ;c i r c l e P t r = &c ;
cout << ∗ p o i n t P t r ; / / Ca l l operator << f o r Po in t/ / Output : ( x , y )= 4 5
cout << ∗ c i r c l e P t r ; / / Ca l l operator << f o r C i r c l e/ / Output : ( x , y , r )= 1 2 0.707
c© A. Amer Polymorphism 15
static_cast examples
/ / Up−cas t ing : using C i r c l e ob jec t as a Po in t ob jec t
Poin t p (4 , 5 ) , ∗ p o i n t P t r ;C i r c l e c (0 .707 , 1 , 2 ) , ∗ c i r c l e P t r ;
/ / Assign C i r c l e ob jec t to Po in t ob jec t p o i n t e r/ / Can only access the Po in t i n f o !p o i n t P t r = &c ;
cout << ∗ p o i n t P t r ; / / Ca l l operator << f o r Po in t/ / Output : ( x , y )= 1 2
c© A. Amer Polymorphism 16
static_cast examples
/ / Down−cas t ing : Po in t to C i r c l e
Poin t p (4 , 5 ) , ∗ p o i n t P t r ;C i r c l e c (0 .707 , 1 , 2 ) , ∗ c i r c l e P t r ;
/ / Assign C i r c l e ob jec t to Po in t ob jec t p o i n t e r/ / Can only access the Po in t i n f o !p o i n t P t r = &c ;
/ / Since p o i n t P t r r e a l l y po in t s to a C i rc le , we can/ / cast i t back to a C i r c l ec i r c l e P t r = stat ic_cast < C i r c l e ∗ >( p o i n t P t r ) ;cout << ∗ p o i n t P t r ; / / Ca l l operator << f o r Po in t/ / Output : ( x , y )= 1 2
cout << ∗ c i r c l e P t r ; / / Ca l l operator << f o r C i r c l e/ / Output : ( x , y , r )= 1 2 0.707
c© A. Amer Polymorphism 17
static_cast examples
/ / Wrong / Unsafe use
Poin t p (4 , 5 ) , ∗ p o i n t P t r ;C i r c l e c (0 .707 , 1 , 2 ) , ∗ c i r c l e P t r ;
/ / Assign C i r c l e ob jec t to Po in t ob jec t p o i n t e r/ / Can only access the Po in t i n f o !p o i n t P t r = &p ;
/ / ! ! ! ! ! ! Can I do t h i s ?c i r c l e P t r = stat ic_cast < C i r c l e ∗ >( p o i n t P t r ) ;cout << ∗ p o i n t P t r ; / / Ca l l operator << f o r Po in t/ / Output : ( x , y )= 4 5
cout << ∗ c i r c l e P t r ; / / Ca l l operator << f o r C i r c l e/ / Output : ( x , y , r )= 4 5 ’ garbage ’
c© A. Amer Polymorphism 18
static_cast summary
Point p(4, 5), *pointPtr;
..
..
.
..
.
.
Memory mapAddress
0x10000x10010x1002
120.707
c
45 p
0x30AA0x30A90x30A8
circlePtrpointPtr
0x30A80x1000
xx
r
xx
r
Circle c(0.707, 1, 2), *circlePtr;
p o i n t P t r = &p ; p o i n t P t r = &c ;c i r c l e P t r = s t a t i c c a s t <C i r c l e∗> ( p o i n t P t r ) ;
c© A. Amer Polymorphism 19
static_cast summary
Point p(4, 5), *pointPtr;
..
..
.
..
.
.
Memory mapAddress
0x10000x10010x1002
120.707
c
45 p
0x30AA0x30A90x30A8
circlePtrpointPtr
0x30A80x1000
xx
r
xx
r
Circle c(0.707, 1, 2), *circlePtr;
p o i n t P t r = &p ; p o i n t P t r = &c ;c i r c l e P t r = s t a t i c c a s t <C i r c l e∗> ( p o i n t P t r ) ;
Safe casting: from a derived object to a base object
Be careful when casting from a base class to a derived classc© A. Amer Polymorphism 19
Object pointer casting: Example
/ / L i s t i n g 15.1 Using po in te r s to access ob jec ts o f base and der ived classesclass Base { / / base c lass
protected : i n t x ;public :Base ( i n t a ) { x = a ; } / / to be used by Derivedvoid set ( i n t a ) { x = a ; } / / to be i n h e r i t e di n t show ( ) const { return x ; } / / to be i n h e r i t e d
} ;
class Derived : public Base { / / der ived c lassprivate : i n t y ;public :
Derived ( i n t a , i n t b ) : Base ( a ) , y ( b ){ } / / empty cons t ruc to r body
void access ( i n t &a , i n t &b ) const / / added i n der ived c lass{ a = Base : : x ; b = y ; }
} ;
c© A. Amer Polymorphism 20
Object pointer casting: Example
i n t x , y ;Derived ∗pD = new Derived (50 ,80 ) ; / / unnamed der ived ob jec t
cout << " 1 . Derived po in te r , ob jec t , and der ived method \ n " ;pD−>access ( x , y ) ; / / no problem : type matchcout <<" x = " <<x <<" y = " <<y <<endl <<endl ; / / x=50 y=80
cout << " 2 . Derived po in te r , der ived ob jec t , base method \ n " ;cout << " x = " << pD−>show ( ) << endl << endl ; / / x = 50Base ∗pB = pD; / / p o i n t e r to same ob jec t
cout << " 3 . Base po in te r , der ived ob jec t , base method \ n " ;cout << " x = " << pB−>show ( ) << endl << endl ; / / x = 50/ / pB−>access ( x , y ) ; / / e r r o r : no access to der ived method
c© A. Amer Polymorphism 21
Object pointer casting: Example
cout << " 4 . Converted po in te r , der ived ob jec t and method \ n " ;( ( Derived ∗ ) pB)−>access ( x , y ) ; / / we know i t i s therecout <<" x = " <<x <<" y = " <<y <<endl <<endl ; / / x=50 y=80pB = new Base ( 6 0 ) ; / / unnamed base ob jec t
cout << " 5 . Base po in te r , base ob jec t , base method \ n " ;cout << " x = " << pB−>show ( ) << endl <<endl ; / / x = 60
cout << " 6 . Converted po in te r , base ob jec t , der ived method \ n " ;( ( Derived ∗ ) pB)−>access ( x , y ) ; / / pass on your own r i s kcout <<" x = " <<x <<" y = " <<y <<endl <<endl ; / / junk ! !
delete pD; delete pB ; / / necessary t i d i n e s s
c© A. Amer Polymorphism 22
Compile time versus Run time
Static type checking / function checkingAlso called compile-time checkingExamples?: d.show(); checked at compile time
Dynamic type checking / function checkingAlso called run-time checking, i.e., at execution timeExamples?: BasePtr->show();
c© A. Amer Polymorphism 23
Polymorphism
An object is denoted by its name (identifier) and the typeassociated with this identifier
c© A. Amer Polymorphism 24
Polymorphism
An object is denoted by its name (identifier) and the typeassociated with this identifier
Polymorphism (dynamic binding, virtual function):The principle that behavior of a function can varydepending on the actual type of an object
With polymorphism:Objects of different classes related by inheritance mayrespond differently to the same member function callThis allows a programmer to manipulate an object withoutknowing what kind of object it is
c© A. Amer Polymorphism 24
Types of polymorphism
Static polymorphism – (static binding or early binding):At compile time (at the earliest possible time):the compiler selects a method from several candidatesSelection is based on the type of the pointer to the object
c© A. Amer Polymorphism 25
Types of polymorphism
Static polymorphism – (static binding or early binding):At compile time (at the earliest possible time):the compiler selects a method from several candidatesSelection is based on the type of the pointer to the object
Dynamic polymorphism – (dynamic binding or late binding):At run time (at the latest possible time):the compiler selects a method from several candidatesBased on the type of the objectThis allows a programmer to manipulate an object withoutknowing what kind of object it is
c© A. Amer Polymorphism 25
Static polymorphism
Recall: In a derived class,you can redefine (this is?) functions of the base class⇒ compile-time solution
c© A. Amer Polymorphism 26
Static polymorphism
Recall: In a derived class,you can redefine (this is?) functions of the base class⇒ compile-time solution
Static polymorphism (early binding):When the compiler selects a method from severalpossible candidates at compile timeThe legality of the implementation(e.g., a member function invocation)is checked at compile timeExample: if Vehicle has a certain member function,Car also has that member function
c© A. Amer Polymorphism 26
Dynamic polymorphism
Dynamic polymorphism (late binding):When the compiler selects a method from severalpossible candidates at run timeThe legality of some types and functions is determinedbased on the dynamic type of the object at run time
Dynamic polymorphism is implemented through virtual functions
c© A. Amer Polymorphism 27
Dynamic polymorphism
Dynamic polymorphism (late binding):When the compiler selects a method from severalpossible candidates at run timeThe legality of some types and functions is determinedbased on the dynamic type of the object at run time
Also called "dynamic binding":the binding to the code that gets called is accomplisheddynamically (at run time)
Dynamic polymorphism is implemented through virtual functions
c© A. Amer Polymorphism 27
Dynamic polymorphism: When?
Suppose:
We have a base class "Shape" with various derived classes"Triangle", "Rectangle", etc.
Each derived class with its own print() member function
Collect objects of these derived classes into an array ofpointers to these objects CLASS ∗ arr[10]
c© A. Amer Polymorphism 28
Dynamic polymorphism: When?
Suppose:
We have a base class "Shape" with various derived classes"Triangle", "Rectangle", etc.
Each derived class with its own print() member function
Collect objects of these derived classes into an array ofpointers to these objects CLASS ∗ arr[10]
But what sort of pointers could we use?
Recall: A derived pointer can be assigned a base pointer⇒ Shape ∗ arr[10]: an array of pointers to the base class
Rectangle rec; arr[5] = &rec;:rec is the actual object; arr[5] is a pointer of type Shape
c© A. Amer Polymorphism 28
Dynamic polymorphism: When?
Assume we want to print the content of each object in thearray arr[i]->print()
Since the pointer points to a Shape object,the print() function of the Shape (base) class is calledNOT the appropriate derived class function!!
Solution? Dynamic binding (using virtual functions)
c© A. Amer Polymorphism 29
Dynamic polymorphism: When?
So: when you have a pointer to an object,this actual object may be of a derived class
A pointer to an object of type Vehicle*maybe actually be pointing to a Car objectA pointer to an object of type Shape*maybe actually be pointing to a Rectangle object
c© A. Amer Polymorphism 30
Dynamic polymorphism: When?
So: when you have a pointer to an object,this actual object may be of a derived class
A pointer to an object of type Vehicle*maybe actually be pointing to a Car objectA pointer to an object of type Shape*maybe actually be pointing to a Rectangle object
Dynamic binding implies that a base class pointer figures outwhich derived class it really points to at run-time
c© A. Amer Polymorphism 30
Dynamic binding
Create a group of related derived classes under a commonpublic base class
Equip each derived class with a function that performsprocessing specific to this derived class
Make sure that each function has the same name andsignature (interface)
Call this function through a base class pointer
c© A. Amer Polymorphism 31
Dynamic binding
Create a group of related derived classes under a commonpublic base class
Equip each derived class with a function that performsprocessing specific to this derived class
Make sure that each function has the same name andsignature (interface)
Call this function through a base class pointer
⇒ The called function does not depend on the type of the pointerthat points to the object
⇒ It depends on the type of the object pointed to by the pointer
c© A. Amer Polymorphism 31
Dynamic binding: Useful?
Before OOP: software reuse when new code call old code
Dynamic binding can improve reuse by letting old code callnew code
c© A. Amer Polymorphism 32
Dynamic binding: Useful?
Before OOP: software reuse when new code call old code
Dynamic binding can improve reuse by letting old code callnew code
Dynamic binding permits software extensibility:With OOP: a new code may be created, compiled, andtestedLater, this code can be called by a framework that waswritten long time agoThere is no need to change the old code:it does not even need to be recompiled
c© A. Amer Polymorphism 32
Dynamic binding: Useful?
Dynamic binding does not make static binding irrelevant
It introduces many additional dimension of complexity
c© A. Amer Polymorphism 33
Dynamic binding: Useful?
Dynamic binding does not make static binding irrelevant
It introduces many additional dimension of complexity
poly.method(...); OR poly->method(...);
Check if the target (here poly) is an object or a pointerIf it is an object:• Only static binding possible• Check the function signature and• Verify if the function call is correctIf the target is a pointer: consider dynamic binding
In most cases: the method being called depends on the typeof the pointer not on the type of the object
c© A. Amer Polymorphism 33
Dynamic binding: a scenario
If the target is a pointer: consider dynamic bindingDefine at which place in the inheritance hierarchy thepointer belongsIf the pointer is of the derived type:only static binding is possibleIf the pointer is of the base type:dynamic binding is possible
c© A. Amer Polymorphism 34
Dynamic binding: a scenario
If the pointer is of the base type: dynamic binding is possibleif the object the pointer points to is of the base type:no dynamic bindingif the object is of a derived type:dynamic binding is possible• If the function called
· is redefined in the appropriate derived class and· has the same name and signature as
the (virtual) function in the base class,
Apply dynamic binding implemented through virtual functions
c© A. Amer Polymorphism 35
Types of member functions
Defined in the base class and inherited in a derived classwithout redefinition
Defined in a derived class without a counterpart in the baseclass
c© A. Amer Polymorphism 36
Types of member functions
Defined in the base class and inherited in a derived classwithout redefinition
Defined in a derived class without a counterpart in the baseclass
Defined in the base class and redefined in a derived classwith the same name and same signature
Defined in the base class and redefined in a derived classwith the same name and different signature
Defined in the base class and redefined in a derived classwith the same name and same signature as virtualIn which case you can apply dynamic binding?
c© A. Amer Polymorphism 36
Virtual functions
A virtual function is a member function of the base class thatcan be redefined at run-time
Even if the object is accessed by a base pointervirtual functions allow derived classesto replace the implementation of a function provided by thebase class at run time
c© A. Amer Polymorphism 37
Virtual functions
A virtual function is a member function of the base class thatcan be redefined at run-time
Even if the object is accessed by a base pointervirtual functions allow derived classesto replace the implementation of a function provided by thebase class at run time
The replacement is always called whenever the object inquestion is of the derived class(even if the object is accessed by a base pointer)
This allows algorithms in the base class to be replaced in thederived class, even if users don’t know about the derivedclass
c© A. Amer Polymorphism 37
Example: without virtual functions
class Shape {protected :i n t width , he igh t ;public :
void set ( i n t a , i n t b ) { width=a ; he igh t=b ; } / / access base pa r t on ly} ;
class Rectangle : public Shape {public :
i n t area ( void ) { return ( width ∗ he igh t ) ; } / / s p e c i f i c to Rect .} ;
class Tr iang le : public Shape {public :
i n t area ( void ) { return ( width ∗ he igh t / 2 ) ; } / / s p e c i f i c to T rg l .} ;
c© A. Amer Polymorphism 38
Example: without virtual functions
Rectangle r e c t ;T r i ang le t r g l ;
Shape ∗ppoly1 = &r e c t ; / / two po in te r s to ob jec ts o f base c lass ShapeShape ∗ppoly2 = & t r g l ; / / They are assigned the addresses of/ / der ived classes r e c t and t r g l ( v a l i d ?)/ / ==> we can only r e f e r the members t h a t/ / Rectangle and Tr iang le i n h e r i t from Shape
ppoly1−>set ( 4 , 5 ) ; / / can use ppoly1 ;ppoly2−>set ( 4 , 5 ) ;
cout << r e c t . area ( ) << endl ; / / cannot use ppoly1 ; Output 20cout << t r g l . area ( ) << endl ; / / cannot use ppoly2 ; Output 10
c© A. Amer Polymorphism 39
Example: without virtual functions
To make it possible for the pointers to the base class toaccess a member, we have to declared it in the base class
But what is the area of an undefined shape?
c© A. Amer Polymorphism 40
Example: without virtual functions
To make it possible for the pointers to the base class toaccess a member, we have to declared it in the base class
But what is the area of an undefined shape?
To access a (virtual) member of a base class we must declareit as virtual so that the use of pointers to base objects can befully applied to derived objects
c© A. Amer Polymorphism 40
Example: with virtual functions
class Shape {protected :i n t width , he igh t ;public :
void set ( i n t a , i n t b ) { width=a ; he igh t=b ; }/ / se t ( ) not v i r t u a l : i t does the same f o r a l l c lassesv i r t u a l i n t area ( void ) / / area ( ) as v i r t u a l f u n c t i o n/ / Does not make much sense here , but we need i t l a t e r{ return ( 0 ) ; } / / v i r t u a l : works s p e c i f i c i n der ived c l s .
} ;
class Rectangle : public Shape {public :
i n t area ( void ) { return ( width ∗ he igh t ) ; }} ;
c© A. Amer Polymorphism 41
Example: with virtual functions
class Tr iang le : public Shape {public :
i n t area ( void ) { return ( width ∗ he igh t / 2 ) ; }} ;
/ / Test ingRectangle r e c t ;T r i ang le t r g l ;Shape poly ;Shape ∗ppoly1 = &r e c t ;Shape ∗ppoly2 = & t r g l ;Shape ∗ppoly3 = &poly ;
c© A. Amer Polymorphism 42
Example: with virtual functions
ppoly1−>set ( 4 , 5 ) ;ppoly2−>set ( 4 , 5 ) ;ppoly3−>set ( 4 , 5 ) ;
/ / dynamic b ind ing :/ / At run−t ime the implementat ion o f the v i r t u a l f u n c t i o n/ / i s replaced by t h a t o f the der ived c lasscout << ppoly1−>area ( ) << endl ; / / ou tput : 20cout << ppoly2−>area ( ) << endl ; / / ou tput : 10cout << ppoly3−>area ( ) << endl ; / / ou tput : 0/ / desp i te v i r t u a l i t y we can dec lare an ob jec t o f type Shape/ / and to c a l l i t s area ( ) f u n c t i o n
c© A. Amer Polymorphism 43
Virtual & non-virtual functions
Non-virtual member functions are resolved staticallyit is selected at compile-time based on the type of the pointerto the object
c© A. Amer Polymorphism 44
Virtual & non-virtual functions
Non-virtual member functions are resolved staticallyit is selected at compile-time based on the type of the pointerto the object
Virtual member functions are resolved dynamicallyit is selected at run-time based on the type of the object (notthe type of the pointer to that object)
Dynamic binding creates extra space and time overhead but...
c© A. Amer Polymorphism 44
Example without virtual functions
class Student {f r iend ostream& operator <<(ostream&, Student &) ;public :
Student ( char∗ pF , char∗ pL ) ;~Student ( ) ;
protected : char∗ f i r s t ; char∗ l a s t ;} ;
class COEN244 : public Student {public :COEN244( char∗ pF , char∗ pL ) ;~COEN244( ) { count−−; }void setGrade ( f loa t , f loa t , f loa t , f l o a t ) ;f l o a t grade ( ) ; / / <===s t a t i c i n t getCount ( ) { return count ; }
private :f l o a t assignment ; f l o a t quiz ; f l o a t midterm ; f l o a t f i n a l ;s t a t i c i n t count ;
} ;c© A. Amer Polymorphism 45
Example without virtual functions
class ELEC311 : public Student {public :ELEC311( char∗ pF , char∗ pL ) ;~ELEC311 ( ) { count−−; }void setGrade ( f loa t , f loa t , f loa t , f l o a t ) ;f l o a t grade ( ) ; / / <===s t a t i c i n t getCount ( ) { return count ; }
private :f l o a t assignment ; f l o a t l a b o r a t o r y ; f l o a t midterm ; f l o a t f i n a l ;s t a t i c i n t count ;
} ;
c© A. Amer Polymorphism 46
Example without virtual functions
class ELEC490 : public Student {public :ELEC490( char∗ pF , char∗ pL ) ;~ELEC490 ( ) { count−−; }void setGrade ( f l o a t ) ;f l o a t grade ( ) ; / / <===s t a t i c i n t getCount ( ) { return count ; }
private :f l o a t p r o j e c t ;s t a t i c i n t count ;
} ;
c© A. Amer Polymorphism 47
Example without virtual functions
void p r i n t I n f o ( const Student ∗ ) ;
void main {COEN244 c1 ( " Jane " , "Doe" ) ;c1 . setGrade (50 , 55 , 25 , 95 ) ;p r i n t I n f o (&c1 ) ;
}
void p r i n t I n f o ( const Student∗ pStud ) {/ / Output name v ia stream i n s e r t i o n over loadcout << ∗pStud << endl ; / / QUESTION??? How do I know what k ind/ / o f Student pStud i s ?cout << pStud−>grade ( ) ; / / We cannot do t h i s ! ! !
}
c© A. Amer Polymorphism 48
Example with virtual functions
class Student {f r iend ostream& operator <<(ostream&, Student &) ;public :
Student ( char∗ pF , char∗ pL ) ;~Student ( ) ;v i r t u a l f l o a t grade ( ) ; / / <===
protected : char∗ f i r s t ; char∗ l a s t ;} ;
class COEN244 : public Student {public :COEN244( char∗ pF , char∗ pL ) ;~COEN244( ) { count−−; }void setGrade ( f loa t , f loa t , f loa t , f l o a t ) ;v i r t u a l f l o a t grade ( ) ; / / <===s t a t i c i n t getCount ( ) { return count ; }
private :f l o a t assignment ; f l o a t quiz ; f l o a t midterm ; f l o a t f i n a l ;s t a t i c i n t count ;
} ; c© A. Amer Polymorphism 49
Example with virtual functions
void void main {COEN244 c1 ( " Jane " , "Doe" ) ;c1 . setGrade (50 , 55 , 25 , 95 ) ;p r i n t I n f o (&c1 ) ;
}
void p r i n t I n f o ( const Student∗ pStud ) {/ / Output name v ia stream i n s e r t i o n over loadcout << ∗pStud << endl ;cout << pStud−>grade ( ) ; / / grade ( ) o f COEN244 c lass w i l l be c a l l e d
}
c© A. Amer Polymorphism 50
Virtual functions central to OO
Virtual functions make OO software extensible and adaptableBecause old code (in the base class) calls new code (in thederived class)
Programming with classes but without dynamic binding iscalled "object based," but not "object oriented"
c© A. Amer Polymorphism 51
Virtual functions: summary
When a base class member function is declared virtual,it permits run-time (dynamic) selection ofthe equivalent member function of the appropriate derivedclass
c© A. Amer Polymorphism 52
Virtual functions: summary
When a base class member function is declared virtual,it permits run-time (dynamic) selection ofthe equivalent member function of the appropriate derivedclass
Base class virtual functions may have their own definitionIt will be called
if the referenced object is a base class object orif the referenced derived class did not define anequivalent member function
Derived classes defining a virtual function need not beexplicitly declared virtual
Polymorphic behavior works with pointers & references ofbase classes
c© A. Amer Polymorphism 52
Virtual functions: Advice
If using public inheritance,many base class member functions should be declared virtualto ensure that the derived class customizations will overridethe base class behavioreven in a context where a base class object is expected
c© A. Amer Polymorphism 53
Abstract Classes
Some classes represent abstract concepts for which objectscannot exist
(There is no reason to create such objects)
Triangle Rectangle Circle
2DShapePerson
Faculty Student Admine
...
... ...Base Base
Derived Derived Derived Derived DerivedDerived/Base
c© A. Amer Polymorphism 54
Abstract Classes
In an inheritance hierarchy with an abstract base class
The functions have to be defined in the derived classes
The equivalent functions in the base classes are calledpure virtual functions virtual void print() =0;
An object of an abstract base class cannot be instantiated
c© A. Amer Polymorphism 55
Abstract Classes
In an inheritance hierarchy with an abstract base class
The functions have to be defined in the derived classes
The equivalent functions in the base classes are calledpure virtual functions virtual void print() =0;
An object of an abstract base class cannot be instantiated
⇒ Abstract Class: a class with at least one pure virtual function
⇒ Abstract Data Type (ADT): An abstract class
c© A. Amer Polymorphism 55
Virtual destructor
You cannot have virtual constructor, but you can have virtualdestructor
A virtual destructor is a virtual function that is needed if wewill delete (using the delete operator) a derived-class objectvia a base-class pointer
c© A. Amer Polymorphism 56
Virtual destructor
You cannot have virtual constructor, but you can have virtualdestructor
A virtual destructor is a virtual function that is needed if wewill delete (using the delete operator) a derived-class objectvia a base-class pointer
void main ( ) {/ / pStud p o i n t s t o a Student o b j e c tStudent∗ pStud = new COEN244( ” John” , ”Smith” ) ;
. . .delete pStud ; / / w i l l c a l l t h e S tudent o b j e c t ’ s d e s t r u c t o r}
⇒ The COEN244 object destructor will not be calledNot all memory is deallocated!!!
c© A. Amer Polymorphism 56
Virtual destructor
c l a s s Student {fr iend ostream& operator <<(ostream&, Student &) ;public :
Student ( char∗ pF , char∗ pL ) ;v i r t u a l ˜ Student ( ) ;v i r t u a l f l o a t grade ( ) ;
protected : char∗ f i r s t ; char∗ l a s t ;} ;
c© A. Amer Polymorphism 57
Virtual destructor
c l a s s Student {fr iend ostream& operator <<(ostream&, Student &) ;public :
Student ( char∗ pF , char∗ pL ) ;v i r t u a l ˜ Student ( ) ;v i r t u a l f l o a t grade ( ) ;
protected : char∗ f i r s t ; char∗ l a s t ;} ;
⇒ When a Student pointer, pointing to a COEN244 object, isdeleted, the COEN244 destructor is called which in turn willcall the Student destructor
⇒ Virtual destructor violate the rule of virtual functions? (name?)but memory leaks are very dangerous
c© A. Amer Polymorphism 57
Virtual destructor
A class should have a virtual destructor unless that class hasNO virtual functions
If we have any virtual functions, then we will probably going toprocess derived objects via a base pointer
Such processing may include invoking a destructor (normallydone implicitly via delete)
c© A. Amer Polymorphism 58
Virtual destructor
A class should have a virtual destructor unless that class hasNO virtual functions
If we have any virtual functions, then we will probably going toprocess derived objects via a base pointer
Such processing may include invoking a destructor (normallydone implicitly via delete)
Recall virtual functions bind to the code associated with theclass of the object, rather than with the class of thepointer/reference
When you say delete basePtr, and the base class has a virtualdestructor, the destructor that gets invoked is the oneassociated with the type of the object *basePtr, rather thanthe one associated with the type of the pointer
c© A. Amer Polymorphism 58
P: a summary@
Classes: provides data abstraction and encapsulationa means to hide implementations but document
Inheritance: promotes software reuse
Polymorphism: offers software extensibility
c© A. Amer Polymorphism 59
Polymorphism: Employee example
class Employee {public :Employee ( const char ∗ , const char ∗ ) ;~Employee ( ) ; / / d e s t r u c t o r rec la ims memoryconst char ∗getFirstName ( ) const ;const char ∗getLastName ( ) const
/ / Pure v i r t u a l f u n c t i o n makes Employee abs t rac t base c lassv i r t u a l double earnings ( ) const = 0; / / pure v i r t u a lv i r t u a l void p r i n t ( ) const ; / / v i r t u a l
private :char ∗ f i rs tName ;char ∗ lastName ;
} ;
c© A. Amer Polymorphism 60
Polymorphism: Employee example
class Boss : public Employee {public :Boss ( const char ∗ , const char ∗ , double = 0 . 0 ) ;void setWeeklySalary ( double ) ;v i r t u a l double earnings ( ) const ;v i r t u a l void p r i n t ( ) const ;
private :double weeklySalary ;
} ;
c© A. Amer Polymorphism 61
Polymorphism: Employee example
class SalaryWorker : public Employee {public :
SalaryWorker ( const char ∗ , const char ∗ , double = 0 . 0 ) ;void se tSa la ry ( double ) ;v i r t u a l double earnings ( ) const ;v i r t u a l void p r i n t ( ) const ;
protected :double sa la ry ; / / weekly sa la ry
} ;
c© A. Amer Polymorphism 62
Polymorphism: Employee example
class HourlyWorker : public Employee {public :
HourlyWorker ( const char ∗ , const char ∗ , double = 0.0 , double = 0 . 0 ) ;void setWage ( double ) ;void setHours ( double ) ;v i r t u a l double earnings ( ) const ;v i r t u a l void p r i n t ( ) const ;
private :double wage ; / / wage per hourdouble hours ; / / hours worked f o r week
} ;
c© A. Amer Polymorphism 63
Polymorphism: Employee example
class CommissionWorker : public Employee {public :
CommissionWorker ( const char ∗ , const char ∗ , double = 0.0 , i n t = 0 ) ;void setCommission ( double ) ;void se tQuan t i t y ( i n t ) ;v i r t u a l double earnings ( ) const ;v i r t u a l void p r i n t ( ) const ;
protected :double commission ; / / amount per i tem soldi n t q u a n t i t y ; / / t o t a l i tems sold f o r week
} ;
c© A. Amer Polymorphism 64
Polymorphism: Employee example
/ / Test ingEmployee∗ l i s t [ 10 ] ;
Boss b ( "CCC" , "TTTTT" , 800 .00) ;
CommissionWorker c1 ( "SSSS" , "QQQQ" , 3 .0 , 150) ;CommissionWorker c2 ( " JJJJ " , "DDDD" , 4 .0 , 60 ) ;
SalaryWorker s1 ( "BBBB" , "VVVVV" , 500) ;SalaryWorker s2 ( "RRRR" , "Red" , 500) ;
HourlyWorker h1 ( "GGGG" , "PPPP" , 17.00 , 3 7 . 5 ) ;HourlyWorker h2 ( "KKKK" , " I I I I " , 13.75 , 40 ) ;HourlyWorker h3 ( "MMM" , "TT" , 10.15 , 18 ) ;
c© A. Amer Polymorphism 65
Polymorphism: Employee example
l i s t [ 0 ] = &b ;l i s t [ 1 ] = &c1 ;l i s t [ 2 ] = &c2 ;l i s t [ 3 ] = &s1 ;l i s t [ 4 ] = &s2 ;l i s t [ 5 ] = &h1 ;l i s t [ 6 ] = &h2 ;l i s t [ 7 ] = &h3 ;
/ / Dynamic Bindingcout << "DYNAMIC BINDING" << endl ;
for ( i n t i = 0 ; i < 8 ; i ++) {l i s t [ i ]−> p r i n t ( ) ; / / using po in te r scout << " earned $ " << (∗ l i s t [ i ] ) . earn ings ( ) ; / / using ob jec ts
c© A. Amer Polymorphism 66
Polymorphism: Employee example
/ / S t a t i c Bindingcout << "STATIC BINDING" << endl ;
/ / access through ob jec ts : no polymorphism / v i r t u a l i t yb . p r i n t ( ) ; cout << " earned $ " << b . earn ings ( ) ;c1 . p r i n t ( ) ; cout << " earned $ " << c1 . earn ings ( ) ;c2 . p r i n t ( ) ; cout << " earned $ " << c2 . earn ings ( ) ;s1 . p r i n t ( ) ; cout << " earned $ " << s1 . earn ings ( ) ;s2 . p r i n t ( ) ; cout << " earned $ " << s2 . earn ings ( ) ;
h1 . p r i n t ( ) ; cout << " earned $ " << h1 . earn ings ( ) ;h2 . p r i n t ( ) ; cout << " earned $ " << h2 . earn ings ( ) ;h3 . p r i n t ( ) ; cout << " earned $ " << h3 . earn ings ( ) ;
c© A. Amer Polymorphism 67
Polymorphism: Person example
/ / L i s t i n g 15.5 Heterogeneous l i s t processing using v i r t u a l f u n c t i o n sclass Person {
protected :char i d [ 1 0 ] ; / / data common to both typeschar∗ name ; / / v a r i a b l e leng th
public :Person ( const char i d [ ] , const char nm [ ] ) / / Kind type{ s t r cpy ( Person : : id , i d ) ; / / copy i d
name = new char [ s t r l e n (nm) + 1 ] ; / / get space f o r namei f (name == 0) { cout << " Out o f memory \ n " ; e x i t ( 0 ) ; }s t r cpy (name,nm) ; / / copy name
}
v i r t u a l void w r i t e ( ) const / / to d i sp lay data{ } / / not much to do at the moment
~Person ( ) / / r e t u r n heap memory{ delete [ ] name ; } / / f o r Person ob jec t on ly
} ;
c© A. Amer Polymorphism 68
Polymorphism: Person example
class Facu l ty : public Person {private :char∗ rank ; / / f o r f a c u l t y on ly
public :Facu l ty ( const char i d [ ] , const char nm[ ] , const char r [ ] )
: Person ( id ,nm) / / i n i t i a l i z a t i o n l i s t{ rank = new char [ s t r l e n ( r ) + 1 ] ;
i f ( rank == 0) { cout << " Out o f memory \ n " ; e x i t ( 0 ) ; }s t r cpy ( rank , r ) ; }
void w r i t e ( ) const / / d i sp lay record{ cout << " i d : " << i d << endl ; / / p r i n t id , name
cout << " name : " << name << endl ;cout << " rank : " << rank <<endl <<endl ; } / / f a c u l t y on ly
~Facu l ty ( ){ delete [ ] rank ; } / / r e t u r n heap memory
} ;
c© A. Amer Polymorphism 69
Polymorphism: Person example
class Student : public Person {private :char∗ major ; / / f o r s tudent on ly
public :Student ( const char i d [ ] , const char nm[ ] , const char m[ ] ): Person ( id ,nm) / / i n i t i a l i z a t i o n l i s t{ major = new char [ s t r l e n (m) + 1 ] ;
i f ( major == 0) { cout << " Out o f memory \ n " ; e x i t ( 0 ) ; }s t r cpy ( major ,m) ;
}void w r i t e ( ) const / / d i sp lay record
{ cout << " i d : " << i d << endl ; / / p r i n t id , namecout << " name : " << name << endl ;cout << " major : " << major <<endl <<endl ; / / s tudent on ly
}~Student ( ) { delete [ ] major ; } / / r e t u r n heap memory
} ;
c© A. Amer Polymorphism 70
Polymorphism: Person example
void read ( i f s t r eam& f , Person∗& person ) { / / read one recordchar k ind [ 8 ] , i d [ 1 0 ] , name[ 8 0 ] , buf [ 8 0 ] ;f . g e t l i n e ( kind , 8 0 ) ; / / recognize the incoming typef . g e t l i n e ( id , 1 0 ) ; / / read i df . g e t l i n e (name, 8 0 ) ; / / read namef . g e t l i n e ( buf , 8 0 ) ; / / rank or major?i f ( strcmp ( kind , "FACULTY" ) == 0){ person = new Facu l ty ( id , name, buf ) ; } / / ob jec t i s Facu l ty
else i f ( strcmp ( kind , "STUDENT" ) == 0){ person = new Student ( id , name, buf ) ; } / / ob jec t i s Student
else{ cout << " Corrupted data : unknown type \ n " ; e x i t ( 0 ) ; }
}
void w r i t e ( const Person∗ p ) / / d i sp lay record{ p−>w r i t e ( ) ; } / / Facu l ty or Student?
c© A. Amer Polymorphism 71
Polymorphism: Person example
/ / Test ingcout << endl << endl ;Person∗ data [ 2 0 ] ; i n t cnt = 0 ; / / a r ray o f po in te r s
i f s t r eam from ( " un iv . dat " ) ; / / i npu t data f i l ei f ( ! from ) { cout << " Cannot open f i l e \ n " ; return 0; }while ( ! from . eof ( ) )
{ read ( from , data [ cn t ] ) ; / / read u n t i l eofcnt ++; }
cout << " To ta l records read : " << cnt << endl << endl ;
for ( i n t i =0; i < cnt ; i ++){ w r i t e ( data [ i ] ) ; } / / d i sp lay data
for ( i n t j =0; j < cnt ; j ++){ delete data [ j ] ; } / / de le te the record
c© A. Amer Polymorphism 72
A sample exam’s problem
Define a XXXX class that inherits from XXXX class ...
Declare base pointers each pointing to a derived object ...
...
Pay attention to the type of the pointer ...
To be continued in class.
c© A. Amer Polymorphism 73
Top Related