Lecture 16 - Virtual Functions and Polymorphism
Lecture 16 - Virtual Functions and Polymorphism
Information Technology
wah
Lecture 16
Virtual Functions and
Polymorphism
Umer Farooq
Review — Accessing Members of
Base and Derived Classes
class B { • The following are legal:–
public: B_obj.m() //B’s m()
void m(); B_obj.n()
void n();
... D_obj.m() //D’s m()
} // class B D_obj.n() //B’s n()
D_obj.p()
class D: public B {
B_ptr->m() //B’s m()
public
B_ptr->n()
void m();
void p();
D_ptr->m() //D’s m()
...
D_ptr->n() //B’s n()
} // class D D_ptr->p()
Review — Accessing Members of
Base and Derived Classes (continued)
class B { • The following are legal:–
public: B_ptr = D_ptr;
void m(); • The following are not legal:–
void n(); D_ptr = B_ptr;
... B_ptr->p();
} // class B Even if B_ptr is known to point
to an object of class D
class D: public B {
public
void m();
void p(); Class D redefines method m()
...
} // class D
Review — Accessing Members of
Base and Derived Classes (continued)
• Access to members of a class object is determined by
the type of the handle.
• Definition: Handle
• The thing by which the members of an object are accessed
• May be
– An object name (i.e., variable, etc.)
– A reference to an object
– A pointer to an object
Review — Accessing Members of
Base and Derived Classes (continued)
• This is referred to as static binding
class Shape {
class Ellipse: public Shape {
public:
void Rotate(); public:
void Rotate();
void Draw();
d to void Draw();
... th o
me ject ...
} the s s f ob }
e
c c k in d o
a
to ight e!
d d l
Nee the r of han
w
d r a r d l es s
e g a
R
Solution – Virtual Functions
• E.g.,
class Shape {
This tells the compiler to add
public: internal pointers to every object
virtual void Rotate(); of class Shape and its derived
virtual void Draw(); classes, so that pointers to
... correct methods can be stored
} with each object.
What if we need Dynamic
Binding?
class Shape { class Rectangle: public Shape
{
public:
virtual void Rotate(); public:
virtual void Draw(); void Rotate();
... void Draw();
...
}
}
• I.e., subclass methods
override the base class class Ellipse: public Shape {
methods public:
void Rotate();
– (if specified)
void Draw();
• C++ dynamically chooses the ...
correct method for the class }
from which the object was
instantiated.
Notes on virtual
class Shape {
public:
virtual void Rotate();
virtual void Draw();
...
}
class Line: public Shape {
public:
void Rotate();
//Use base class Draw method
...
}
Summary – Based and Derived
Class Pointers
• Base-class pointer pointing to base-class object
– Straightforward
• Derived-class pointer pointing to derived-class object
– Straightforward
• Base-class pointer pointing to derived-class object
– Safe
– Can access non-virtual methods of only base-class
– Can access virtual methods of derived class
• Derived-class pointer pointing to base-class object
– Compilation error
Abstract and Concrete Classes
• Abstract Classes
– Classes from which it is never intended to instantiate any objects
• Incomplete—derived classes must define the “missing pieces”.
• Too generic to define real objects.
Definitions
– Normally used as base classes and called abstract base classes
• Provide appropriate base class frameworks from which other
classes can inherit.
• Concrete Classes
– Classes used to instantiate objects
– Must provide implementation for every member function they
define
Pure virtual Functions
• Example
virtual void draw() const = 0;
Employee
BasePlusCommissionEmployee
Employee Example
class Employee {
public:
Employee(const char *, const char *);
~Employee();
char *getFirstName() const;
char *getLastName() const;
protected:
char *firstName;
char *lastName;
};
Employee::Employee(const char *first, const char *last)
{
firstName = new char[ strlen(first) + 1 ];
strcpy(firstName, first);
lastName = new char[ strlen(last) + 1 ];
strcpy(lastName, last);
}
private:
float commission; // amount per item sold
unsigned quantity; // total items sold for week
};
CommissionWorker::CommissionWorker(const char *first,
const char *last, float c, unsigned q)
: Employee(first, last) // call base-class constructor
{
commission = c > 0 ? c : 0;
quantity = q > 0 ? q : 0;
}
void CommissionWorker::setCommission(float c)
{ commission = c > 0 ? c : 0; }
void CommissionWorker::setQuantity(unsigned q)
{ quantity = q > 0 ? q : 0; }
float CommissionWorker::earnings() const
{ return commission * quantity; }
void CommissionWorker::print() const
{
cout << endl << "Commission worker: " << getFirstName()
<< ' ' << getLastName();
}
class HourlyWorker : public Employee {
public:
HourlyWorker(const char *, const char *,
float = 0.0, float = 0.0);
void setWage(float);
void setHours(float);
virtual float earnings() const;
virtual void print() const;
private:
float wage; // wage per hour
float hours; // hours worked for week
};
HourlyWorker::HourlyWorker(const char *first, const char *last,
float w, float h)
: Employee(first, last) // call base-class constructor
{
wage = w > 0 ? w : 0;
hours = h >= 0 && h < 168 ? h : 0;
}
void HourlyWorker::setWage(float w) { wage = w > 0 ? w : 0; }
// Set the hours worked
void HourlyWorker::setHours(float h)
{ hours = h >= 0 && h < 168 ? h : 0; }
// Get the HourlyWorker's pay
float HourlyWorker::earnings() const { return wage * hours; }
// Print the HourlyWorker's name
void HourlyWorker::print() const
{
cout << endl << " Hourly worker: " << getFirstName()
<< ' ' << getLastName();
}
class BasePlusCommissionEmployee:public
CommissionWorker
{
private:
float baseSalary;
public:
BasePlusCommissionEmployee(const char* ,
const char* , float =0.0, unsigned =0,float =0.0);
void setBaseSalary(float sal) {
baseSalary = sal;
}
float getBaseSalary(void) const {
return baseSalary;
}
void print() const;
float earnings() const;
};
BasePlusCommissionEmployee::BasePlusCommissionEmployee(co
nst char* first, const char* last, float c,
unsigned q,float sal)
:CommissionWorker(first,last,c,q)
{
baseSalary=(sal);
}
void BasePlusCommissionEmployee::print() const
{
cout << "\nbase-salaried commission employee: ";
CommissionWorker::print(); // code reuse
} // end function print
float BasePlusCommissionEmployee::earnings() const
{
return getBaseSalary() + CommissionWorker::earnings();
return 0;
}