1 of 41

C++ Classes – Polymorphism (Pt.1)

C. Papachristos

Robotic Workers Lab

University of Nevada, Reno

CS-202

2 of 41

Course , Projects , Labs:

Your 5th Project Deadline is this Wednesday 3/4.

  • PASS Sessions held as scheduled, get all the help you need!

  • 24-hrs delay after Project Deadline incurs 20% grade penalty.
  • Past that, NO Project accepted. Better send what you have in time!

Monday

Tuesday

Wednesday

Thursday

Friday

Sunday

 

 

 

Lab (8 Sections)

 

 

CLASS

PASS

Session

CLASS

 

PASS

Session

Project DEADLINE

NEW Project

 PASS

Session

 PASS

Session

Course Week

CS-202 C. Papachristos

3 of 41

Today’s Topics

CS-202 C. Papachristos

Polymorphism Concepts & Practice

  • Abstraction via Polymorphism

Polymorphism in Inheritance

  • Base Class Pointer(s)
  • Arrays (or generally Data Structures) of Base Class Pointers

virtual Class Methods

Late Binding

  • Static Binding vs Dynamic Binding

4 of 41

Polymorphism (prelude)

CS-202 C. Papachristos

Polymorphism & Inheritance

Polymorphism means “the ability to take many forms”.

  • Allowing a single (Remember: Overriding vs Overloading) behavior to take on many type-dependent forms.
  • Hence, grants the ability to manipulate Objects in a type-independent way.

Pointers of Base Class-type:

  • They are used to address “Common Ancestor”-type Objects from a Class Hierarchy.

BigRig

Vehicle

Car

Plane

etc…

SUV

Sedan

Van

Jeep

5 of 41

Polymorphism (prelude)

CS-202 C. Papachristos

Polymorphism & Inheritance

Base Class-type Pointers :

  • A Pointer of a Base Class type can point to an Object of a Derived Class type.

SUV suv1;

Sedan sedan1, sedan2;

Jeep jeep1;

Car * suv1_Pt = &suv1;

Car * sedan1_Pt = &sedan1, * sedan2_Pt = &sedan2;

Car * jeep1_Pt = &jeep1;

This is valid: A Derived Class (SUV, Sedan, Van, Jeep) “is a type of” Base Class (Car).

  • Note: A 1-way relationship:

A Derived Class Pointer cannot point to a Base Class Object.

6 of 41

Polymorphism

CS-202 C. Papachristos

Polymorphism & Inheritance

Supported through Pointers of Base Class-type:

  • Problem: Implement a single catalog of different types of Cars available for rental.

SUV

Sedan

Van

Jeep

Derived

Class(es)

Base Class

Car

0 1 2 98 99

suv1

suv2

sedan1

sedan85

van56

All are

Cars

7 of 41

Polymorphism

CS-202 C. Papachristos

Polymorphism & Inheritance

Supported through Pointers of Base Class-type:

  • Problem: Implement a single catalog of different types of Cars available for rental.

? Multiple arrays, one for each Child Class type.

? Combine all Child Classes into one giant Class with redundant useless info for every kind of car.

Accomplished with a single array of Base Class Pointers !

  • Polymorphism in the Data Structure.
  • Inheritance enables this.

Note:

  • Only Array of Base Class Pointers !

(not array of Objects because different Derived Classes require different allocation, and arrays don’t do that).

  • Dynamic Structures too (later on std::vector etc.)

8 of 41

Polymorphism

CS-202 C. Papachristos

Polymorphism & Inheritance

Base Class-type Pointers :

  • A pointer of a Parent Class type can point to an Object of a Child Class type.

SUV suv1;

Sedan sedan1, sedan2;

Jeep jeep1;

Car * suv1_Pt = &suv1;

Car * sedan1_Pt = &sedan1, * sedan2_Pt = &sedan2;

Car * jeep1_Pt = &jeep1;

Car *cars_Pt_arr[4];

cars_Pt_arr[0] = suv1_Pt;

cars_Pt_arr[1] = sedan1_Pt;

cars_Pt_arr[2] = sedan2_Pt;

cars_Pt_arr[3] = jeep1_Pt;

Note:

  • Array of Base Class Pointers (not Objects) !

9 of 41

Polymorphism

CS-202 C. Papachristos

Polymorphism & Methods

Refers to the ability to associate many meanings to one function name,

  • by means of Late Binding !

Associating many meanings to one function:

  • Fundamental principle of Object-Oriented Programming.
  • virtual functions provide this capability.

10 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

Property that indicates something that is not concretely defined.

  • It does not need to be exactly finalized at the point where we wish to invoke it.
  • That point represents the execution of an actual functionality …

virtual Function

  • A function that “shall be there” to call when required.
  • We can “use it / call it” – virtually in our code (compile-time) , without finalizing on that same spot what it will do exactly !
  • The actual call will depend on the context of our program when it actually gets executed (run-time) !

11 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

What is the purpose?

  • In effect, implements an incomplete behavior.
  • If it is indeed “used”, resulting code exhibits an uncertain behavior.

Power of Programming Abstraction:

  • Incomplete is not concrete.

but

  • Incomplete is also modular !

12 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Classes for several kinds of GeometricFigures:

  • Rectangles, Circles, Ovals, etc.

Each figure is an Object of different Class:

class Rectangle data: center point , height , width.

class Circle data: center point , radius.

All Derived from one Parent Class:

  • GeometricFigure

Rectangle

m_height

m_width

Circle

m_radius

Inherited

GeometricFigure

m_center

13 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Classes for several kinds of GeometricFigures:

  • Rectangles, Circles, Ovals, etc.

Each figure is an Object of different Class:

class Rectangle data: height, width, center point.

class Circle data: center point, radius.

All Require a function: redraw()

  • Different instructions for each figure type !

Rectangle

m_height

m_width

Circle

m_radius

redraw()

redraw()

?

?

GeometricFigure

m_center

m_center

m_width

m_height

m_center

m_radius

14 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Each class needs different drawing function.

  • Can be called redraw() in each different Class:

Rectangle r;�Circle c;

r.redraw(); //Calls Rectangle class’s redraw()c.redraw(); //Calls Circle class’s redraw()

Nothing new here (yet).

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

GeometricFigure

m_center

15 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Parent Class GeometricFigure contains functions�that apply to “all” figure types:

center(): moves a figure to center of screen.

  • Erases 1st, then re-draws Object.

So GeometricFigure::center() would:

  • have to use function redraw() !
  • Would look something like:

GeometricFigure::center() {

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

}

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

GeometricFigure

m_center

redraw()

center()

16 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Parent Class GeometricFigure contains functions�that apply to “all” figure types:

center(): moves a figure to center of screen.

  • Erases 1st, then re-draws Object.

So GeometricFigure::center() would:

  • have to use function redraw() !

Complications:

  • How to know there is some other redraw() function to call, from�some other Class, since we are just implementing a Base Class method ?
  • All the compiler knows is that the call to redraw() happens inside the�context of GeometricFigure (the Base Class), so it will use that one!

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

redraw()

?

?

GeometricFigure

m_center

redraw()

center()

17 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Consider a new kind of figure comes later into play:�class Triangle: Derived from GeometricFigure.

Function center() is Inherited.

  • Will it work for Triangles?

It uses redraw(), which is different for each figure!

redraw()

Rectangle

redraw()

Circle

redraw()

Triangle

redraw()

GeometricFigure

m_center

redraw()

center()

?

18 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

By-Example:

Consider a new kind of figure comes later into play:�class Triangle: Derived from GeometricFigure.

It will use GeometricFigure::redraw() :

  • won’t work for Triangles.

Want Inherited function center() to use

function Triangle::redraw().

But Class Triangle wasn’t even written when�GeometricFigure::center() was.

Rectangle

redraw()

Circle

redraw()

Triangle

redraw()

GeometricFigure

m_center

redraw()

center()

redraw()

?

19 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

How? virtual class methods give the answer.

Declaring a member function as virtual tells the C++ compiler:

  • I will act “As-If I don’t know” the exact context of the function call.� At the moment, as you are putting together your code (i.e., at compile-time) !

  • I will wait until it is actually used in the program (at runtime)

  • Then invoke the specific implementation that corresponds to the type of the � specific Object (i.e., the context) that made the call !

Called “Late Binding” or “Dynamic Binding”.

  • Also “Dynamic Method Dispatch” is the actual mechanism that performs resolution of which overridden method is to be called (more on that later…)

20 of 41

Polymorphism

CS-202 C. Papachristos

class GeometricFigure {

public:

void redraw(){ cout<<"Not much"<<endl; }

void center(){

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

}

protected:

Point m_center;

};

class Rectangle : public GeometricFigure {

public:

void redraw(){

//Uses special members m_width , m_height

}

private:

double m_width;

double m_height;

};

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

redraw()

?

?

GeometricFigure

m_center

redraw()

center()

Usual:

Static Binding

21 of 41

Polymorphism

CS-202 C. Papachristos

class GeometricFigure {

public:

virtual void redraw(){ cout<<Not much"<<endl; }

void center(){

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

}

protected:

Point m_center;

};

class Rectangle : public GeometricFigure {

public:

virtual void redraw(){

//Uses special members m_width , m_height

}

private:

double m_width;

double m_height;

};

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

Polymorphic:

Dynamic Binding

redraw()

GeometricFigure

m_center

redraw()

center()

22 of 41

Polymorphism

CS-202 C. Papachristos

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

Polymorphic:

Dynamic Binding

redraw()

GeometricFigure

m_center

redraw()

center()

Virtual – via Base class Pointers

By-Example:

gf_p = &gf;

gf_p->center() ;

gf_p->center() ;

gf_p->center() ;

(1)

(2)

(3)

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

Common Inherited Behavior (coming from Base class)

GeometricFigure * gf_p;

GeometricFigure gf;

Rectangle rect;

Circle circ;

gf_p = &rect;

gf_p = &circ;

23 of 41

Polymorphism

CS-202 C. Papachristos

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

Polymorphic:

Dynamic Binding

redraw()

GeometricFigure

m_center

redraw()

center()

Virtual – via Base class Pointers

By-Example:

gf_p = &gf;

gf_p->center() ;

gf_p->center() ;

gf_p->center() ;

(1)

(2)

(3)

Ends up calling “appropriate” Method Override Dynamically

(1)

(2)

(3)

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

gf_p = &rect;

gf_p = &circ;

GeometricFigure * gf_p;

GeometricFigure gf;

Rectangle rect;

Circle circ;

24 of 41

Polymorphism

CS-202 C. Papachristos

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

Polymorphic:

Dynamic Binding

redraw()

GeometricFigure

m_center

redraw()

center()

Virtual – via Base class Pointers

By-Example:

gf_p = &gf;

gf_p->center() ;

gf_p->center() ;

gf_p->center() ;

(1)

(2)

(3)

Ends up calling “appropriate” Method Override Dynamically

(1)

(2)

(3)

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

gf_p = &rect;

gf_p = &circ;

Remember�These are in fact equivalent to:�this->redraw();

GeometricFigure * gf_p;

GeometricFigure gf;

Rectangle rect;

Circle circ;

25 of 41

Polymorphism

CS-202 C. Papachristos

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

Polymorphic:

Dynamic Binding

redraw()

GeometricFigure

m_center

redraw()

center()

Virtual – via Base class References

By-Example:

gf_r.center();

gr_r.center();

gc_r.center();

(1)

(2)

(3)

Ends up calling “appropriate” Method Override Dynamically

(1)

(2)

(3)

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

GeometricFigure gf; GeometricFigure & gf_r = gf;

Rectangle rect; GeometricFigure & gr_r = rect;

Circle circ; GeometricFigure & gc_r = circ;

26 of 41

Polymorphism

CS-202 C. Papachristos

Rectangle

redraw()

m_height

m_width

Circle

redraw()

m_radius

redraw()

redraw()

GeometricFigure

m_center

redraw()

center()

Virtual

By-Example:

GeometricFigure gf;

Rectangle rect;

Circle circ;

gf.center() ;

rect.center() ;

circ.center() ;

(1)

(2)

(3)

Object-based call means everything is known at compile-time

(1)

(2)

(3)

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

m_center.x = CENTER_X;

m_center.y = CENTER_Y;

redraw();

Usual:

Static Binding

27 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

Another Example (a larger application problem):

Record-keeping program module for automotive parts store:

  • Sales tracking.

Issue:

  • Don’t know all types of sales yet.

Initially just working with regular retail sales,

but later on, discount sales, mail-order sales, etc. might come along.

These might additionally depend on other factors besides just price, tax.

28 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

Another Example (a larger application problem):

Program must:

  • Compute daily gross sales.
  • Calculate largest/smallest sales of day.
  • Average daily sales.

All will come from individual bills.

  • But many functions for computing bills will be added “later” !

Function for computing a bill will be virtual !

29 of 41

Polymorphism

CS-202 C. Papachristos

Keyword virtual

Another Example (a larger application problem):

class Sale {� public:Sale();� Sale(double price);� double getPrice() const;

virtual double bill() const;

double savings(const Sale&

other) const;� private:double m_price;�};

A general Super-class:

  • Represents sales of a single item with no added discounts or charges.

A virtual Member Function:

  • Impact: Later, Derived classes of Sale can define their own versions of Function bill().
  • Other Member Functions of Sale will use version based on Object of that Derived class !
  • They won’t automatically use Sale ’s version!

30 of 41

Polymorphism

CS-202 C. Papachristos

Keyword virtual

Another Example (a larger application problem):

double Sale::savings(const Sale & other) const�{� return (bill() – other.bill());�}

bool operator<(const Sale & first,� const Sale & second)�{� return (first.bill() < second.bill());�}

A Member Function of Super-Class Sale.

A non-Member Function – Operator ( < ).

Both use the virtual Member Function bill().

31 of 41

Polymorphism

CS-202 C. Papachristos

Keyword virtual

Another Example (a larger application problem):

class DiscountSale : public Sale {� public:DiscountSale();� DiscountSale(double price,� double discount);� double getDiscount() const;� void setDiscount(double newDisc);

virtual double bill() const;

private:double m_discount;�};

The Derived Sub-class:

  • Represents more specialized sales type.

The Base class’ virtual Function:

  • Automatically virtual in Derived Class.
  • Not required to have virtual keyword but typically included for readability.
  • The Derived class will implement its own version of the virtual Function.

32 of 41

Polymorphism

CS-202 C. Papachristos

Keyword virtual

Another Example (a larger application problem):

double DiscountSale::bill() const�{� double fraction = m_discount/100;� return (1 – fraction)*getPrice();�}

DiscountSale’s Member Function bill() implemented differently than Sale’s:

  • Member Function savings() and non-Member operator<(…) will use

this definition of bill() for all Objects of DiscountSale Class

(instead of defaulting to version defined in Sales).

Derived Class’ more particular implementation of the virtual Member Function.

virtual qualifier does not appear in implementation (only declaration).

33 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

Remember:

  • Base Class Sale written before Derived Class DiscountSale.
  • Member Function savings() and non-Member operator<(…) compiled before�even having the concept of a DiscountSale Class.

Yet consider the call:�DiscountSale d1, d2;�d1.savings(d2);

  • Powerful !

The call inside savings() to function bill() has no problem to work with the definition of bill() from a DiscountSale Class.

34 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

Remember:

  • Base Class Sale written before Derived Class DiscountSale.
  • Member Function savings() and non-Member operator<(…) compiled before�even having the concept of a DiscountSale Class.

  • Powerful !

Even non-Member Functions can be Polymorphic.

Can pass a Pointer or a Reference to a Base Class Object.

  • Subsequent Method calls are Dynamically Bound.

  • Old code is dynamically calling new code when new Derived Classes are defined!

35 of 41

Polymorphism

CS-202 C. Papachristos

Static vs Dynamic Binding

What is the difference with Method Overriding as known to us by now?

  • Determining which Method in the Hierarchy to call.

Static Binding (overriding as of yet)

Compiler –at “compile-time”– determines binding.

Dynamic Binding (overriding with keyword virtual)

System –at “run-time”– determines binding.

36 of 41

Polymorphism

CS-202 C. Papachristos

virtual Function(s) & Covariant return Type(s)

Overriding virtual Class Functions does not allow to change return Type.

  • For the case of Dynamic Binding, it is required that:

“whenever the Base Class Method can be called, it should also be directly replaceable by call to Derived Class Method with no change to calling code (i.e. implicit casting is not allowed).”

  • C++ Standard enforces this by restricting return types:

class BaseClass{

public:

virtual int intFxn();

};

class DerivedClass : public BaseClass{

public:

virtual double intFxn();

};

Note: Not a case of different signatures due to conflicting return types,

it is C++ standard-enforced requirement for Dynamic Binding.

(i.e. virtual Functions)

!

37 of 41

Polymorphism

CS-202 C. Papachristos

virtual Function(s) & Covariant return Type(s)

Overriding virtual Class Functions does allow to have different “Covariant” return Type(s).

  • Typical case: Base Class & Derived Class Pointers:

class BaseClass{

public:

virtual BaseClass * covarFxn();

};

class DerivedClass : public BaseClass{

public:

virtual DerivedClass * covarFxn();

};

Note: Covariant return types (Pointers!) allowed

in the context of Dynamic Binding.

(i.e. virtual Functions)

38 of 41

Polymorphism

CS-202 C. Papachristos

Remember: Static vs Dynamic Binding

Static Binding

class Animal {

public:

void eat(){

cout<<"Food"<<endl;

}

};

class Lion : public Animal{

public:

void eat(){

cout<<"Meat"<<endl;

}

};

int main(){

Animal animal;

Lion lion;

animal.eat(); // Food

lion.eat(); // Meat

Animal * animal_Pt = &animal;

animal_Pt->eat(); //Food

Animal * animalLion_Pt = &lion;

animalLion_Pt->eat(); //Food

return 0;

}

Objects

Object

Pointers

Static Binding

39 of 41

Polymorphism

CS-202 C. Papachristos

Remember: Static vs Dynamic Binding

Dynamic Binding

class Animal {

public:

virtual void eat();

};

void Animal::eat(){

cout<<"Food"<<endl;

}

class Lion : public Animal{

public:

virtual void eat();

};

void Lion::eat(){

cout<<"Meat"<<endl;

}

int main(){

Animal animal;

Lion lion;

animal.eat(); // Food

lion.eat(); // Meat

Animal * animal_Pt = &animal;

animal_Pt->eat(); //Food

Animal * animalLion_Pt = &lion;

animalLion_Pt->eat(); //Meat

return 0;

}

Objects

Object

Pointers

Dynamic Binding

40 of 41

Polymorphism

CS-202 C. Papachristos

Virtual

Consider:

In C++ programs, nothing happens by “magic”.

  • Explanation involves Late Binding.

Tell C++ compiler to wait until function is used in program, and decide which definition to use based on the current calling Object.

Disadvantages:

  • Overhead – Late binding is “on the fly” at runtime.
  • Use of more storage – “Hidden elements” in how it is implemented.

If virtual functions are not necessary, they should be avoided.

41 of 41

Time for Questions !

CS-202

CS-202 C. Papachristos