slide 1 polymorphism: part i. slide 2 summary: derived class * ‘is-a’ relationship n different...

73
Slide 1 Polymorphism: Part I

Post on 21-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 1

Polymorphism: Part I

Page 2: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 2

Summary: Derived Class

‘is-a’ relationship Different from ‘has-a’ or ‘uses-a’, or … by class-in-class

Public inheritance Public Private

‘protected’ Constructors/destructors Redefinition (over-riding) …

COMP152 2

Page 3: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 3

What is Polymorphism? Polymorphism: poly + morph (biology): the existence of two or more forms of individuals

within the same animal species

In programming languages Objects belonging to different types (classes) call methods of

the same name, but of different behavior.

‘over-loading’ is one type of polymorphism: static binding Same names, but different arguments

‘over-riding’ by ‘virtual function’ is another type: dynamic binding

Same names, but different ‘classes’ with the same hierarchy

COMP1523

Page 4: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 4

Polymorphism with inheritance hierarchies

“Program in the general” vs. “program in the specific” Process objects of classes that are part of the same

hierarchy as if they are objects of a single class E.g., vehicles 4-wheel vehicle passenger car sport car Objects can be created in any part of the chain of hierarchy

Each object performs the correct tasks for that object’s type Different actions occur depending on the type of object

New classes can be added with little or no modification to existing code

COMP152 4

Page 5: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 5

class Employee {double pay();…

}

class Manager : public Employee {double pay();

}

double Employee::pay() {…

}

double Manager::pay() {return 10*Employee::pay();

}

int main () {Employee e;

Manager m;

cout << e.pay();

cout << m.pay();

}

Page 6: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 6

Motivation

the pointers/references are logically ‘compatible’ for the base and derived classes

with ‘static typing or binding’, at compilation, it can only be fixed based on the ‘type/class’ of the pointers/references, but not the actual objects (base or derived class)

the ‘resolution’ should be delayed to the ‘run-time’, so to introduce ‘dynamic binding’

‘virtual function’ explicitly enforces ‘dynamic binding’

Page 7: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 7

Pointers and Classes

class Employee {double pay();…

}

class Manager : public Employee {double pay();

}

int main() {Employee* ep;

ep = new Employee; // OK…ep = new Manager; // OK

Manager* mp;

mp = new Manager; // OK…mp = new Employee; // error!

}

A ‘manager’ is an ‘emloyee’, so a base class pointer (employee) can point to a ‘manager’ object

But, a derived class pointer (Manager) CANNOT point to a base class object (employee) as an ‘employee’ is not necessarily a ‘manager’!

Page 8: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 8

Good Pointers, but Wrong Functions!

void printPay(const Employee& e) {cout << e.pay() << endl;

}

int main() {Employee e;Manager m;

printPay(e); // ok for ‘employee’

printPay(m); // ??? for ‘manager’ ???}

class Employee {double pay();…

}

class Manager : public Employee {double pay();

}

int main() {Employee* ep;

ep = new Employee;…ep = new Manager;

ep->pay()? // always Employee::pay(),

// never Manager::pay()!!!

Page 9: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 9

‘Virtual’ is polymorphic

class Employee {virtual double pay();…

}

class Manager : public Employee {double pay();

}

Employee* ep;

ep = new Employee;…ep = new Manager;

ep->pay(); // always the right one, // either Employee::pay(), or

Manager::pay()!!!

Page 10: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 10

Static and Dynamic Binding The compiler determines which version of the function or

class to use during the compilation time for Function overloading Function and class template substantiations

Which version is called must be deferred to run time This is dynamic binding

COMP152 10

Page 11: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 11

(non-virtual) Static and (virtual) Dynamic Binding

Non-virtual member functions are resolved statically at compilation time i.e. the member function is selected based on the type of the

pointer (or reference) to the object

Virtual member functions are resolved dynamically at run time i.e. the member function is selected based on the type of the

object!

COMP152 11

Page 12: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 12

Example with more details

Page 13: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 13

Invoking functions with pointers/references

CommissionEmployee1.h, CommissionEmployee1.cpp, BasePlusCommissionEmployee1.h, BasePlusCommissionEmployee1.cpp, test1a.cpp

COMP152 13

Cannot aim derived-class pointer to a base-class object Aim base-class pointer at base-class object

Invoke base-class functionality Aim derived-class pointer at derived-class object

Invoke derived-class functionality Aim base-class pointer at derived-class object

Because derived-class object is an (inherited) object of base class Can only invoke base-class functionalities

Invoked functionality depends on the pointer/reference type used to invoke the function (which is base or derived object). Therefore, if it is base pointer, even if it points to a derived-class object, it invokes the

functionality of base class

Page 14: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 14

Function earnings and print will be redefined in derived classes to calculate the employee’s earnings

Function print will be redefined in derived class to print the employee’s information

COMP152 14

class CommissionEmployee{public: CommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0 ); void setFirstName( const string & ); // set first name string getFirstName() const; // return first name ...

double earnings() const; // calculate earnings void print() const; // print CommissionEmployee object

CommissionEmployee1.h

Page 15: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 15

Redefine functions earnings and print

COMP152 15

class BasePlusCommissionEmployee : public CommissionEmployee{public: BasePlusCommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0 ); void setBaseSalary( double ); // set base salary double getBaseSalary() const; // return base salary

double earnings() const; // calculate earnings void print() const; // print BasePlusCommissionEmployee object

private: double baseSalary; // base salary}; // end class BasePlusCommissionEmployee

BasePlusCommissionEmployee1.h

Page 16: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 16

COMP152 16

Print base-class and derived-class objects: commission employee: Sue Jonessocial security number: 222-22-2222gross sales: 10000.00commission rate: 0.06 base-salaried commission employee: Bob Lewissocial security number: 333-33-3333gross sales: 5000.00commission rate: 0.04base salary: 300.00 Calling print with base-class pointer tobase-class object invokes base-class print function:

commission employee: Sue Jonessocial security number: 222-22-2222gross sales: 10000.00commission rate: 0.06

Test1a.cpp sample output (1/2)

Page 17: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 17

COMP152 17

Calling print with derived-class pointer toderived-class object invokes derived-class print function: base-salaried commission employee: Bob Lewissocial security number: 333-33-3333gross sales: 5000.00commission rate: 0.04base salary: 300.00 

Calling print with base-class pointer to derived-class objectinvokes base-class print function on that derived-class object: commission employee: Bob Lewissocial security number: 333-33-3333gross sales: 5000.00commission rate: 0.04

Test1a.cpp sample output (2/2)

Page 18: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 18

The pointer must be a base-class pointer, pointing to a derived-class object All the base class functions of the derived object can be called. This is not a

problem because derived class inherits all the functions from the base class. Because it is a base class pointer, cannot access the members of derived-

class even if the base-class pointer is pointing to the derived-class object Aim a derived-class pointer at a base-class object is an error

C++ compiler generates error CommissionEmployee (base-class object) is not a BasePlusCommissionEmployee

(derived-class object) This is because

A derived-class pointer is supposed to be able to access all the derived-class member functions that it points to

If the pointer is pointing to a base class, some of these derived-class functions may not even be available at the base class

COMP152 18

Page 19: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 19

Cannot assign base-class object to derived-class pointer

COMP152 19

CommissionEmployee commissionEmployee( "Sue", "Jones", "222-22-2222", 10000, .06 );BasePlusCommissionEmployee *basePlusCommissionEmployeePtr = 0;

// aim derived-class pointer at base-class object// Error: a CommissionEmployee is not a BasePlusCommissionEmployeebasePlusCommissionEmployeePtr = &commissionEmployee;

Test1b.cpp

Page 20: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 20

tester1c: Aiming base-class pointer at derived-class object

Calling functions that exist in base class causes base-class functionality to be invoked

Calling functions that do not exist in base class (may exist in derived class) will result in error Derived-class members cannot be accessed from base-class pointers

COMP152 20

// aim base-class pointer at derived-class objectcommissionEmployeePtr = &basePlusCommissionEmployee;

// invoke base-class member functions on derived-class// object through base-class pointer (allowed)string firstName = commissionEmployeePtr->getFirstName();

Page 21: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 21

CommissionEmployee2.h

Declaring earnings and print as virtual allows them to be overridden Overridden means superceding the base class codes Not redefined, meaning that the original function of the base class

still exists

COMP152 21

class CommissionEmployee{public: CommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0 ); void setFirstName( const string & ); // set first name string getFirstName() const; // return first name ...

virtual double earnings() const; // calculate earnings virtual void print() const; // print CommissionEmployee object

Page 22: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 22

BasePlusCommissionEmployee2.h

Functions earnings and print are already virtual – good practice to declare virtual even with overriding function (though optional)

COMP152 22

class BasePlusCommissionEmployee : public CommissionEmployee{public: BasePlusCommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0 ); void setBaseSalary( double ); // set base salary double getBaseSalary() const; // return base salary

virtual double earnings() const; // calculate earnings virtual void print() const; // print

private: double baseSalary; // base salary}; // end class BasePlusCommissionEmployee

Page 23: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 23

tester2.cpp (1/3)

Aiming base-class pointer at base-class object and invoking base-class functionality

COMP152 23

// output objects using static bindingcout << "Invoking print function on base-class and derived-class " << "\nobjects with static binding\n\n";commissionEmployee.print(); // static bindingbasePlusCommissionEmployee.print(); // static binding // output objects using dynamic bindingcout << "\n\n\nInvoking print function on base-class and “ << "derived-class \nobjects with dynamic binding";

// aim base-class pointer at base-class object and printcommissionEmployeePtr = &commissionEmployee;cout << "\n\nCalling virtual function print with base-class pointer" << "\nto base-class object invokes base-class " << "print function:\n\n";commissionEmployeePtr->print(); // invokes base-class print

Page 24: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 24

tester2.cpp (2/3)

Aiming derived-class pointer at derived-class object and invoking derived-class functionality

COMP152 24

// aim derived-class pointer at derived-class object and printbasePlusCommissionEmployeePtr = &basePlusCommissionEmployee;cout << "\n\nCalling virtual function print with derived-class “ << "pointer\nto derived-class object invokes derived-class “ << "print function:\n\n";basePlusCommissionEmployeePtr->print();

Page 25: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 25

tester2.cpp (3/3)

Aiming base-class pointer at derived-class object and invoking derived-class functionality via polymorphism and virtual functions

COMP152 25

// aim base-class pointer at derived-class object and printcommissionEmployeePtr = &basePlusCommissionEmployee;cout << "\n\nCalling virtual function print with base-class pointer" << "\nto derived-class object invokes derived- class " << "print function:\n\n";

// polymorphism; invokes BasePlusCommissionEmployee's print;// base-class pointer to derived-class objectcommissionEmployeePtr->print();

Page 26: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 26

tester2.cpp Sample Output (1/3)

COMP152 26

Invoking print function on base-class and derived-classobjects with static binding commission employee: Sue Jonessocial security number: 222-22-2222gross sales: 10000.00commission rate: 0.06 base-salaried commission employee: Bob Lewissocial security number: 333-33-3333gross sales: 5000.00commission rate: 0.04base salary: 300.00  Invoking print function on base-class and derived-classobjects with dynamic binding

Page 27: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 27

tester2.cpp Sample Output (2/3)

COMP152 27

Calling virtual function print with base-class pointerto base-class object invokes base-class print function: commission employee: Sue Jonessocial security number: 222-22-2222gross sales: 10000.00commission rate: 0.06 Calling virtual function print with derived-class pointerto derived-class object invokes derived-class print function:

base-salaried commission employee: Bob Lewissocial security number: 333-33-3333gross sales: 5000.00commission rate: 0.04base salary: 300.00

Page 28: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 28

tester2.cpp Sample Output (3/3)

COMP152 28

Calling virtual function print with base-class pointerto derived-class object invokes derived-class print function: base-salaried commission employee: Bob Lewissocial security number: 333-33-3333gross sales: 5000.00commission rate: 0.04base salary: 300.00

Page 29: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 29

Pure Virtual Functions and Abstract Classes

Page 30: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 30

Abstract Classes

‘Employee’: both base class and derived class are useful objects

‘Shape’ represents an abstract concept for which objects cannot exist.

‘shape’ makes sense only as the base of some class derived from it.

class Employee {string firstName;string familyName;…

}

class Manager : public Employee {list<Employee*> group;…

}

class Shape {void rotate(int);void draw();…

}

class Circle : public Shape {…

}

Shape s; ???

Page 31: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 31

Virtual Functions

A ‘virtual’ function in a base class will be redefined in each derived class

class Shape {virtual void rotate(int);virtual void draw();…

}

class Circle : public Shape {public:

void rotate(int);void draw();…

private:int radius;

}

Page 32: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 32

‘Pure’ Virtual Functions

A ‘virtual’ function is ‘made pure’ by the initializer = 0.

class Shape {virtual void rotate(int) = 0;virtual void draw() = 0;…

}

class Circle : public Shape {public:

void rotate(int);void draw();…

private:int radius;

}

Page 33: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 33

Abstract Class A class with one or more pure virtual functions is an ‘abstract’

class, And no objects of that abstract class can be created! An abstract class is only used as an interface and as a base for

other classes.class Shape {

virtual void rotate(int) = 0;virtual void draw() = 0;…

}

class Circle : public Shape {public:

void rotate(int);void draw();…

private:int radius;

}

Shape s; // error!!!Circle c;

Page 34: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 34

A pure virtual function that is not defined in a derived class remains a pure virtual function, so the derived class is still an abstract class.

class Shape {virtual void rotate(int) = 0;virtual void draw() = 0;…

}

class Polygon : public Shape {public:

bool is_closed() { return true; }}

Polygon p; // error!!!

Page 35: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 35

Polymorphism: Part II

Page 36: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 36

A Test: What is the Output?

COMP152 36

#include <iostream>using namespace std;

class A {public: A() {} void f() {cout << "A::f()" << endl;}};

class B: public A {public: B() {} void f() {cout << "B::f()" << endl;}};

class C: public B {public: C() {} void f() {cout << "C::f()" << endl;}};

int main(){ A* z = new A; z->f(); delete z; A* x = new B; x->f(); delete x; A* y = new C; y->f(); delete y; return 0;}

Page 37: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 37

COMP152 37

Output:A::f()A::f()A::f()

Page 38: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 38

Change A* to B* or C*?

COMP152 38

Page 39: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 39

A Test:if we add virtual to class A?

COMP152 39

class A {public: A() {} virtual void f() {cout << "A::f()" << endl;}};

Page 40: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 40

COMP152 40

Output:A::f()B::f()C::f()

Page 41: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 41

The three corner-stones of OOP

Encapsulation Inheritance Polymorphism

Page 42: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 42

Encapsulation Languages such as Pascal and C facilitated development of

structured programs Need for ability to extend and reuse software became evident

This leads to object-oriented programming where objects are built on top of other objects

Data and basic operations for processing the data are encapsulated into a single “entity”. This is made possible with introduction of Modules Libraries Packages

Implementation details are separated from class definition Client code must use only public operations Implementation may be changed without affecting client code

COMP152 42

Page 43: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 43

Encapsulation with Inheritance Some basic class features may be re-used in other

classes A class can be derived from another class

New class inherits data and function members from the original class

Reusable for the new class Example:

Consider the need to add, for example max() and min(), functions to a stack

Could simply add these functions to the class But … alters already proven code

It is better to build “on top” of the proven stack by adding the functions The new class is inherited or derived from the stack class Obviously, this concept is different from creating a new class with

a stack as its member objectCOMP152 43

Page 44: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 44 Inheritance Features and Advantages

Software reusability Often used in computer game design

Create new class from existing class Seamlessly absorb existing class’s data and behaviors Enhance with new capabilities

Derived class inherits from base class More specialized group of objects (e.g., a character moves, but a

soldier and a giant move differently) Behaviors inherited from base class

Can customize Additional behaviors

COMP152 44

Page 45: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 45

Pure Virtual Functions and Abstract Classes

We can use the abstract base class to declare pointers and references Can point to objects of any concrete class derived from the abstract class Programs typically use such pointers and references to manipulate

derived-class objects polymorphically Polymorphism is particularly effective for implementing software

systems Reading or writing data from and to different devices of the same base

class Iterator class

Can traverse all the objects in a container

COMP152 45

Page 46: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 46

COMP152 46

#include <iostream>

using namespace std;

class base{public: virtual void print() = 0; virtual void print2() = 0;};

class derived1: public base{public: virtual void print(){ cout << "derived1\n"; } virtual void print2(){} // must have this line, // otherwise compiler complains in main()};

class derived2: public base{public: virtual void print(){ cout << "in derived2\n"; } // do not need to define print2() here as // derived2 is not a concrete class};

class derived3: public derived2{public: virtual void print2(){ cout << "In derived3\n"; }};

int main(){ derived1 d1; // derived2 d2; compiler complains: // the following virtual functions are abstract: // void base::print2() derived3 d3;

d1.print(); d3.print(); // can do that! d3.print2();

return 1;}

derived1in derived2In derived3

Page 47: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 47

dyanmic_cast

We can always cast a (derived) class to one of its base classes If p is a base class pointer, T* is a derived class pointer

Statically, it is impossible (static_cast fails!) But dynamically at run-time, we look at the object pointed to by p (if any).

If the object is of class T, then returns a pointer type T* to that object Otherwise, 0 is returned.

COMP152 47

dynamic_cast<T*>(p);

p is a pointer or reference

Page 48: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 48

COMP152 48

#include <iostream>#include <typeinfo>#include <string>

using namespace std;

class base{public: virtual void print(){ cout << "Base object\n";}};

class derived: public base{public: virtual void print(){ cout << "Derived object\n"; }};

int main(){

base* bptr[2]; // check whether it points to a derived obj derived* is_derived; bptr[0] = new base(); bptr[1] = new derived();

// check whether the pointer can be successfully cast is_derived = dynamic_cast<derived*> (bptr[0]);

if(is_derived) cout << "bptr[0] is a derived object.\n"; else cout << "bptr[0] is a base object.\n"; is_derived = dynamic_cast<derived*> (bptr[1]); if(is_derived) // derived class is_derived -> print(); // call derived functions else // is_derived is NULL; base class bptr[1] -> print(); // call base functions

return 0;}

bptr[0] is a base object.Derived object

Page 49: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 49

Virtual ? Constructors/Destructors

COMP152 49

Page 50: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 50

Constructors cannot be virtual

Destructors can be virtual Usually they should be virtual to have ‘polymorphic’ behavior

COMP152 50

Page 51: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 51

Virtual Destructors Nonvirtual destructors

Destructors that are not declared with keyword virtual If a derived-class object is destroyed explicitly by applying the delete operator to a base-class pointer to the object, the behavior is undefined

This is because delete may be applied on a base-class object, instead of the derived class

virtual destructors Declared with keyword virtual

That means that all derived-class destructors are virtual With that, if a derived-class object is destroyed explicitly by

applying the delete operator to a base-class pointer to the object, the appropriate derived-class destructor is then called

Appropriate base-class destructor(s) will execute afterwards

COMP152 51

Page 52: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 52

COMP152 52

#include <iostream>using namespace std;

class Base{public: virtual ~Base() { cout <<"Base Destroyed\n"; }};

class Derived: public Base{public: virtual ~Derived() { cout << "Derived Destroyed\n"; }};

int main(){ Derived d; Base* bptr = new Derived(); delete bptr; // explicit delete call the destructor immediately bptr = new Derived(); // the object will be deleted by garbage collection // after program exits, and hence no destructor statement return 0;}

Derived Destroyed (for “delete bptr”)Base DestroyedDerived Destroyed (for object d going out of scope)Base Destroyed

Page 53: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 53

Case Study: Payroll System Using Polymorphism

Page 54: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 54

A Payroll System Enhanced CommissionEmployee-BasePlusCommissionEmployee

hierarchy using an abstract base class Abstract class Employee represents the general concept of an employee

Declares the “interface” to the hierarchy Each employee has a first name, last name and social security number

Earnings calculated differently and objects printed differently for each derived class

COMP152 54

Page 55: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 55 Creating Abstract Base Class Employee

Provides various get and set functions Provides functions earnings and print

Function earnings depends on type of employee, so declared pure virtual Not enough information in class Employee for a default implementation

Function print is virtual, but not pure virtual Default implementation provided in Employee

Example maintains a vector of Employee pointers Polymorphically invokes proper earnings and print functions

COMP152 55

Page 56: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 56

Polymorphic Interface

COMP152 56

Page 57: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 57

Employee.h

Function earnings is pure virtual, not enough data to provide a default, concrete implementation

Function print is virtual, default implementation provided but derived-classes may override

COMP152 57

// pure virtual function makes Employee abstract base class virtual double earnings() const = 0; // pure virtual virtual void print() const; // virtual

private: string firstName; string lastName; string socialSecurityNumber;}; // end class Employee

Page 58: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 58

Creating Concrete Derived Class SalariedEmployee inherits from Employee

Includes a weekly salary Overridden earnings function incorporates weekly salary Overridden print function incorporates weekly salary

Is a concrete class (implements all pure virtual functions in abstract base class)

COMP152 58

Page 59: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 59

SalariedEmployee.h

SalariedEmployee inherits from Employee, must override earnings to be concrete

Functions earnings and print in the base class will be overridden (earnings defined for the first time)

COMP152 59

class SalariedEmployee : public Employee {public: SalariedEmployee( const string &, const string &, const string &, double = 0.0 ); void setWeeklySalary( double ); // set weekly salary double getWeeklySalary() const; // return weekly salary

// keyword virtual signals intent to override virtual double earnings() const; // calculate earnings virtual void print() const; // print SalariedEmployee objectprivate: double weeklySalary; // salary per week};

Page 60: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 60

SalariedEmployee.cpp

COMP152 60

// calculate earnings; // override pure virtual function earnings in Employeedouble SalariedEmployee::earnings() const { return getWeeklySalary(); } // end function earnings

// print SalariedEmployee's information void SalariedEmployee::print() const{ cout << "salaried employee: "; Employee::print(); // reuse abstract base-class print function cout << "\nweekly salary: " << getWeeklySalary();} // end function print

Page 61: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 61

Creating Concrete Derived Class HourlyEmployee inherits from Employee

Includes a wage and hours worked Overridden earnings function incorporates the employee’s wages

multiplied by hours (taking time-and-a-half pay into account) Overridden print function incorporates wage and hours worked

Is a concrete class (implements all pure virtual functions in abstract base class)

COMP152 61

Page 62: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 62

HourlyEmployee.h

COMP152 62

class HourlyEmployee : public Employee {public: HourlyEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0 ); void setWage( double ); // set hourly wage double getWage() const; // return hourly wage

void setHours( double ); // set hours worked double getHours() const; // return hours worked

// keyword virtual signals intent to override virtual double earnings() const; // calculate earnings virtual void print() const; // print HourlyEmployee object

private: double wage; // wage per hour double hours; // hours worked for week}; // end class HourlyEmployee

Page 63: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 63

Creating Concrete Derived Class CommissionEmployee inherits from Employee

Includes gross sales and commission rate Overridden earnings function incorporates gross sales and commission

rate Overridden print function incorporates gross sales and commission rate

Concrete class (implements all pure virtual functions in abstract base class)

ComissionEmployee.h, CommissionEmployee.cpp

COMP152 63

Page 64: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 64 Creating Indirect Concrete Derived Class

BasePlusCommissionEmployee inherits from CommissionEmployee Includes base salary

Overridden earnings function that incorporates base salary Overridden print function that incorporates base salary

Concrete class Not necessary to override earnings to make it concrete, can inherit

implementation from CommissionEmployee Although we do override earnings to incorporate base salary

COMP152 64

Page 65: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 65

BasePlusComissionEmployee.h

BasePlusCommissionEmployee inherits from CommissionEmployee, which is already concrete

COMP152 65

class BasePlusCommissionEmployee : public CommissionEmployee {public: BasePlusCommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0 );

void setBaseSalary( double ); // set base salary double getBaseSalary() const; // return base salary

// keyword virtual signals intent to override virtual double earnings() const; // calculate earnings virtual void print() const; // print BasePlusCommissionEmployee objectprivate: double baseSalary; // base salary per week}; // end class BasePlusCommissionEmployee

Page 66: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 66 BasePlusComissionEmployee.cpp

Overridden earnings and print functions incorporate base salary

COMP152 66

// calculate earnings;// override pure virtual function earnings in Employeedouble BasePlusCommissionEmployee::earnings() const{ return getBaseSalary() + CommissionEmployee::earnings(); } // end function earnings

// print BasePlusCommissionEmployee's information void BasePlusCommissionEmployee::print() const{ cout << "base-salaried "; CommissionEmployee::print(); // code reuse cout << "; base salary: " << getBaseSalary();} // end function print

Page 67: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 67 Demonstrating Polymorphic Processing

Create objects of types SalariedEmployee, HourlyEmployee, CommissionEmployee and BasePlusCommissionEmployee Demonstrate manipulating objects with static binding

Using name handles rather than pointers or references Compiler can identify each object’s type to determine which print and

earnings functions to call Demonstrate manipulating objects polymorphically

Uses a vector of Employee pointers Invoke virtual functions using pointers and references

COMP152 67

Page 68: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 68

payroll.cpp (1/3)

vector of Employee pointers, will be used to demonstrate dynamic binding

COMP152 68

// create vector of four base-class pointers vector < Employee * > employees( 4 );

// initialize vector with Employees employees[ 0 ] = &salariedEmployee; employees[ 1 ] = &hourlyEmployee; employees[ 2 ] = &commissionEmployee; employees[ 3 ] = &basePlusCommissionEmployee;

cout << "Employees processed polymorphically via dynamic binding:\n\n";

Page 69: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 69

payroll.cpp (2/3)

Demonstrate dynamic binding using pointers, then references

COMP152 69

// call virtualViaPointer to print each Employee's information // and earnings using dynamic binding cout << "Virtual function calls made off base-class pointers:\n\n";

for ( size_t i = 0; i < employees.size(); i++ ) virtualViaPointer( employees[ i ] );

// call virtualViaReference to print each Employee's // information and earnings using dynamic binding cout << "Virtual function calls made off base-class references:\n\n";

for ( size_t i = 0; i < employees.size(); i++ ) virtualViaReference( *employees[ i ] ); // note dereferencing

return 0;} // end main

Page 70: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 70

payroll.cpp (3/3)

Using references and pointers cause virtual functions to be invoked polymorphically

COMP152 70

// call Employee virtual functions print and earnings off a // base-class pointer using dynamic bindingvoid virtualViaPointer( const Employee * const baseClassPtr ){ baseClassPtr->print(); cout << "\nearned $" << baseClassPtr->earnings() << "\n\n";} // end function virtualViaPointer

// call Employee virtual functions print and earnings off a // base-class reference using dynamic bindingvoid virtualViaReference( const Employee &baseClassRef ){ baseClassRef.print(); cout << "\nearned $" << baseClassRef.earnings() << "\n\n";} // end function virtualViaReference

Page 71: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 71

payroll.cpp Sample Output (1/3)

COMP152 71

Employees processed individually using static binding: salaried employee: John Smithsocial security number: 111-11-1111weekly salary: 800.00earned $800.00 hourly employee: Karen Pricesocial security number: 222-22-2222hourly wage: 16.75; hours worked: 40.00earned $670.00 commission employee: Sue Jonessocial security number: 333-33-3333gross sales: 10000.00; commission rate: 0.06earned $600.00 base-salaried commission employee: Bob Lewissocial security number: 444-44-4444gross sales: 5000.00; commission rate: 0.04; base salary: 300.00earned $500.00

Page 72: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 72

payroll.cpp Sample Output (2/3)

COMP152 72

Employees processed polymorphically using dynamic binding: Virtual function calls made off base-class pointers: salaried employee: John Smithsocial security number: 111-11-1111weekly salary: 800.00earned $800.00 hourly employee: Karen Pricesocial security number: 222-22-2222hourly wage: 16.75; hours worked: 40.00earned $670.00 commission employee: Sue Jonessocial security number: 333-33-3333gross sales: 10000.00; commission rate: 0.06earned $600.00 base-salaried commission employee: Bob Lewissocial security number: 444-44-4444gross sales: 5000.00; commission rate: 0.04; base salary: 300.00earned $500.00

Page 73: Slide 1 Polymorphism: Part I. Slide 2 Summary: Derived Class * ‘is-a’ relationship n Different from ‘has-a’ or ‘uses-a’, or … by class-in-class * Public

Slide 73

payroll.cpp Sample Output (3/3)

COMP152 73

Virtual function calls made off base-class references: salaried employee: John Smithsocial security number: 111-11-1111weekly salary: 800.00earned $800.00 hourly employee: Karen Pricesocial security number: 222-22-2222hourly wage: 16.75; hours worked: 40.00earned $670.00  commission employee: Sue Jonessocial security number: 333-33-3333gross sales: 10000.00; commission rate: 0.06earned $600.00 base-salaried commission employee: Bob Lewissocial security number: 444-44-4444gross sales: 5000.00; commission rate: 0.04; base salary: 300.00earned $500.00