CSC 213 Code Chapter 10, Fall 2007
Notre Dame University–Louaize · Program Design and Data Abstraction II · 5 pages
More CSC 213 files
- Code Chapter 9 · Fall 2007FileView
- Useful File Number Systems · Fall 2007FileView
- Useful File IO Stream · Fall 2007FileView
- Code Chapter 8 · Fall 2007FileView
- Useful File Operator Precedence and Associativity · Fall 2007FileView
- Useful File ASCII Table · Fall 2007FileView
- Code Chapter 7 · Fall 2007FileView
- Code Chapter 14 · Fall 2007FileView
Show the text of this file
Virtual Functions and Polymorphism
1
Virtual Function and Polymorphism allow the design
and implementation of systems that are easily
extensible…
Programs written to generically process objects of all
existing classes in a hierarchy…
This can be achieved by taking the advantage of the
“pointer to derived class” compatibility with a “pointer
to its base class”…
<Pointer-to-base-class> = <Pointer-to-derived-class>
<Pointer-to-base-class> = & <Object-of-derived-class>
As seen earlier, a pointer to the base-class can point to
any object of its derived classes without the need of
explicit casting…
The same rule applies for a base-class reference to a
derived object…
Virtual Functions and Polymorphism
2
LLeettss ccoonnssiiddeerr tthhee ffoolllloowwiinngg sscceennaarriioo…
…
#include <iostream.h>
class pet {
public:
void speak() {cout << "can't speak \n";}
};
class dog : public pet {
public:
void speak() { cout << "woofffff! \n"; }
};
class cat : public pet {
public:
void speak() { cout << "meawwwww! \n"; }
};
class bird : public pet {
public:
void speak() { cout << "squeekkk! \n"; }
};
void main() {
dog spike;
cat tom;
bird tweety;
pet *cage= &tom ;
spike.speak();
tweety.speak();
tom.speak();
cage->speak();[j1]
static_cast<bird*>(cage)->speak();[j2]
}
Virtual Functions and Polymorphism
3
W
Whhaatt aabboouutt tthhiiss sscceennaarriioo ??????…
…
void main() {
pet *cage[3];
cage[0] = new dog;
cage[1] = new cat;
cage[2] = new bird;
cage[1]->speak();[j3]
static_cast<bird*>(cage[1])->speak();[j4]
}
Virtual Functions and Polymorphism
4
AA ssoolluuttiioonn !!!!!!…
…
Virtual Functions
#include <iostream.h>
class pet {
public:
virtual[JAN5] void speak() {cout << "can't speak
\n";}
};
class dog : public pet {
public:
void speak() { cout << "woofffff! \n"; }
};
class cat : public pet {
public:
void speak() { cout << "meawwwww! \n"; }
};
class bird : public pet {
public:
void speak() { cout << "squeekkk! \n"; }
};
void sayIt(pet &pRf, pet *pPr) {
pRf.speak();
// Dynamic binding.[JAN6]
pPr->speak();
// Dynamic binding.[JAN7]
}
Virtual Functions and Polymorphism
5
void main() {
bird tweety;
pet *cage[3], &pRef_1 = tweety;
cage[0] = new dog;
cage[1] = new cat;
cage[2] = new bird;
cage[2]->speak();
// Dynamic binding.[JAN8]
cage[0]->speak();
cage[1]->speak();
pRef_1.speak();
// Dynamic binding.[JAN9]
tweety.speak();
// Static binding.[JAN10]
pet &pRef_2 = *cage[1];
pRef_2.speak();
// Dynamic binding.[JAN11]
sayIt(*cage[0], cage[2]);
}
• By declaring function speak as vviirrttuuaall, and by using:
!
a base-class pointer that points to a derived-class
object…
!
a base-class reference that references a derived
class object…
the program will chose the correct derived class speak
dynamically at run-time… Dynamic binding…
• When a virtual function is called by the object name
using the “dot-operator”… the function called is the one
defined for (or inherited by) the class of that particular
object… Static binding…
Virtual Functions and Polymorphism
6
M
Moorree rreeaalliissttiicc sscceennaarriioo…
…
#include <iostream.h>
class Polygon {
public:
void setPoly (int a, int b) {
width = a;
height = b;
}
virtual[JAN12] int area() {return 0;}
protected:
int width, height;
};
class Rectangle: public Polygon {
public:
int area () { return (width * height); }
};
class Triangle: public Polygon {
public:
int area() {return (width * height / 2);}
};
void main () {
Rectangle rect;
Polygon *polyPtr[2], &polyRef = rect ;
polyPtr[0] = new Rectangle;
polyPtr[1] = new Triangle;
polyPtr[0]->setPoly(4,5);
polyPtr[1]->setPoly(2,50);
polyRef.setPoly(1,30);
cout << polyPtr[0]->area()[JAN13] << endl;
cout << polyPtr[1]->area() << endl;
cout << polyRef.area()[JAN14] << endl;
}
Virtual Functions and Polymorphism
7
Abstract and Concrete Classes
• Abstract classes:
!
Sole purpose is to
provide a base class
for other classes…
Too generic to define real objects…
!
No objects of an abstract base class can be
instantiated… Syntax error…
!
Can have pointers and references…
• Concrete classes:
!
Classes that can instantiate objects…
!
Provide specifics to make real objects…
Square, Circle, etc…
• A class is made aabbssttrraacctt by declaring one or more of its
virtual function to be “pure”…
A pure virtual function is one with an initializer of =0 in
its declarations…
class Polygon {
public:
void setPoly (int a, int b) {
width = a;
height = b;
}
virtual int area() =0;
virtual void print() const;[JAN15]
protected:
int width, height;
};
TwoDimensionalShape
Circle Square Triangle
Virtual Functions and Polymorphism
8
#include <iostream.h>
class Polygon {
public:
void setPoly (int a, int b) {
width = a;
height = b;
}
virtual int area() =0;
virtual void print()=0;
protected:
int width, height;
};
class Rectangle: public Polygon {
public:
int area () { return (width * height); }
void print() {
cout << width << endl;
cout << height << endl;
}
};
class Triangle : public Polygon[JAN16] {
public:
int area() {return (width * height / 2);}
};
void main () {
Polygon poly;[JAN17]
Rectangle rect;
Triangle trgl;[JAN18]
}
Syntax Error…
Virtual Functions and Polymorphism
9
Polymorphism
• From the Greek:
PPoollyy
# M
Maannyy
M
Moorrpphh
# SShhaappee
• In OOP:
!
Ability for objects of different classes (related by
inheritance) to respond differently to the same
function call…
• PPoollyym
moorrpphhiissm
m is implemented via vviirrttuuaall functions…
!
When a request is made trough a base class
pointer (or reference) to use a virtual function,
C++ chooses the correct overridden function in the
appropriate derived class associated with the
object…
• Needless to say that nnoonn--vviirrttuuaall function behave in the
same manner discussed in the inheritance chapter…
!
If non-virtual member function defined in
multiple classes and called from base-class pointer
then the base-class version is used…
!
If called from derived-class pointer then derived-
class version is used…
! NNoonn--ppoollyym
moorrpphhiicc behavior…
Virtual Functions and Polymorphism
10
#include <iostream.h>
class Polygon {
public:
void setPoly (int a, int b) {
width = a;
height = b;
}
virtual int area() { return 0;}
void print() const {
cout << "Width:" << width << " - "
<< "Height:" << height << endl;
}
protected:
int width, height;
};
class Rectangle: public Polygon {
public:
int area() {return (width * height);}
};
class Triangle: public Polygon {
public:
int area() {return (width * height / 2);}
void print() const {
cout << "Base:" << width << " - "
<< "Height:" << height << endl;
}
};
Virtual Functions and Polymorphism
11
void main() {
Rectangle rect;
Triangle trgl;
Polygon *polyPtr,
&polyRefR = rect,
&polyRefT = trgl;
rect.setPoly(10,2);
trgl.setPoly(30,3);
rect.print();
trgl.print();
cout << rect.area() << endl;
cout << trgl.area() << endl;
polyPtr = &trgl;
polyPtr->print();
cout << polyPtr->area() << endl;
polyPtr = ▭
polyPtr->print();
cout << polyPtr->area() << endl;
polyRefT.print();
cout << polyRefT.area() << endl;
polyRefR.print();
cout << polyRefR.area() << endl;
}[JAN19]
Virtual Functions and Polymorphism
12
Case Study: A Payroll system using Polymorphism
• Perform different payroll calculations for different
types of employees (base class Employee):
!
Boss - fixed weekly salary
!
CommissionWorker - flat base salary + commission
!
PieceWorker - paid according to items produced
!
HourlyWorker - hourly wage + overtime
Employee
firstName
lastName
getFirstName( )
getLastName( )
earnings( )
print( )
Boss
WeeklySalary
setWeeklySalary( )
earnings( )
print( )
HourlyWorker
wage
hours
setWage( )
setHours( )
earnings( )
print( )
PieceWorker
wagePerPiece
quantity
setWage( )
setQuantity( )
earnings( )
print( )
CommissionWorker
salary
commission
quantity
setSalary( )
setCommission( )
setQuatity( )
earnings( )
print( )
Virtual Functions and Polymorphism
13
Virtual destructor
• Recall
#include <iostream.h>
class A {
public:
A(int x = 0) {
valA = x;
cout << "Constructor: valA= "
<< valA <<endl;
}
~A() {
cout << "Destructor: valA= "
<< valA << endl;
}
private:
int valA;
};
void main() {
A *aPtr, aObj(5);
aPtr = new A[2];
delete [] aPtr;
}[JAN20]
• An object allocated using the new operator must be
explicitly deallocated using the delete operator… It is
at the deletion time that the destructors is called…
Virtual Functions and Polymorphism
14
#include <iostream.h>
class basA {
public:
basA (int a) { x = a; }
virtual[JAN21] ~basA() {
cout << "Base destructor... x = " << x << endl;
}
protected:
int x;
};
class drvA: public basA {
public:
drvA(int a, int b) : basA(a) {y = b;}
int getA() {return y;}
void setA(int a) { y = a;}
~drvA() {
cout << "Derived destructor... y = " << y <<endl;
}
private:
int y;
};
void main() {
basA *basPtr;
drvA *drvPtr;
drvPtr=new drvA(10, 20);
delete drvPtr;
drvPtr=new drvA(100, 200);
basPtr = drvPtr;
delete basPtr;[JAN22]
}
Virtual Functions and Polymorphism
15
• Problem:
!
If a base-class pointer to a derived object is
deleted, the base-class destructor will act on the
object…
• Solution:
!
Declare a virtual base-class destructor to ensure
that the appropriate destructor will be called
Virtual Functions and Polymorphism
16
Case Study: Inheriting Interface and Implementation
Shape
virtual area( )
virtual volume( )
virtual printShapeName( )
virtual print( )
Point
x
y
setPoint( )
getX( )
getY( )
printShapeName( )
print( )
Circle
radius
setRadius( )
getRadius( )
area( )
printShapeName( )
print( )
Cylinder
height
setheight( )
getheight( )
area( )
volume( )
printShapeName( )
print( )
Virtual Functions and Polymorphism
17
Polymorphism, virtual Functions and Dynamic Binding
“Under the Hood”
The fundamental idea behind polymorphism is that the
compiler does not know which function to call
compile-time…the appropriate function will be
selected run-time….
A common implementation is the following…
• An object containing virtual member functions holds
as its first data member a hidden field, pointing to an
array of pointers containing the addresses of the
virtual member functions …
• The hidden data member is usually called the
vpointer…
• The array of virtual member function addresses is
called the vtable…
• Final Note:
!
Polymorphism requires some overhead…
!
Polymorphism is not used in STL (Standard
Template Library) to optimize performance…
point
circle
printShapeName
print()