Document 15057530

advertisement
Course Name: High Level Programming Language
Year
: 2010
Polymorphism
Lecture 10
Learning Outcomes
At the end of this lecture, students are capable of:
Understanding the concept of Polymorphism in C++
programming.
3
Outline Materi
•
•
•
•
Polymorphism
Abstract Base Classes
Virtual Function
Pure Virtual Function
4
Base and Derived Pointers
vehicle
motorcycle
car
truck
• Base class pointers can point to derived class objects
• E.g., all trucks are vehicles, so a vehicle pointer can point to
a truck.
• Derived class pointers cannot point to base class objects
– Not all vehicles are trucks, so a truck pointer cannot point to a
vehicle.
Base and Derived Pointers
class truck : public vehicle {
protected:
int capacity;
};
class vehicle {
protected:
char type[50];
};
class car : public vehicle {
protected:
int numPassengers;
};
class bicycle : public vehicle {
protected:
int serialNum;
};
Base and Derived Pointers 2
void main() {
vehicle *v;
bicycle *b;
truck *t = new truck();
v = t;
// b = v; (WRONG)
car *c = new car();
v = new bicycle();
delete t;
delete c;
delete v;
}
Polymorphism
• Method to allow programs to generically
process objects
• Don’t have to know all about derived
classes in advance
• Good for modular reusable code
– Generic linked lists, a queue of different
types of people, etc.
Object Polymorphism
• A method expecting a Car object can only accept Car
objects
• A method expecting Vehicle objects can accept any
object derived from the Vehicle class
•Car
•Truck
•Bus
• There’s also function polymorphism
Polymorphism 2
• Normally, when an object or pointer to an
object calls a function, it does so statically
– I.e., determined at compile time
• Another way is to allow for it to be DYNAMIC,
and determined at run-time
• This allows you to treat objects generically,
provided they have the same interface
– This is called polymorphism
• How do we do this? Base classes with
virtual functions.
Virtual Function
• A virtual function is a member
function
– declared within a base class
– redefined by a derived class (i.e.
overriding)
• It can be used to support run-time
polymorphism.
Example
class base {
public:
int i;
base (int x) { i = x; }
virtual void func() {cout << i; }
};
Example
class derived : public base {
public:
derived (int x) : base (x) {}
// The keyword virtual is not needed.
void func() {cout << i * i; }
};
Example
int main() {
base ob(10), *p;
derived d_ob(10);
p = &ob;
p->func();
p = &d_ob;
p->func();
}
// use base’s func()
// use derived’s func()
Pure Virtual Functions
• A pure virtual function has no definition relative to the
base class.
• Only the function’s prototype is included.
• General form:
virtual type func-name(paremeter-list) = 0
Example: area
class area {
public:
double dim1, dim2;
area(double x, double y)
{dim1 = x; dim2 = y;}
// pure virtual function
virtual double getarea() = 0;
};
Example: rectangle
class rectangle : public area {
public:
// function overriding
double getarea() {
return dim1 * dim2;
}
};
Example: triangle
class triangle : public area {
public:
// function overriding
double getarea() {
return 0.5 * dim1 * dim2;
}
};
Facts about Virtual Functions
• When a virtual function is called, the
computer determines at runtime the
appropriate derived function to execute.
• The base class has the virtual functions
• New derived classes can be added that
implement their own versions of these
functions
• Override the base virtual functions in derived
classes!
More Example of Virtual Functions
class person {
protected:
char *name;
char *phone;
public:
person(char *n, char *p);
virtual void print();
};
class student : public person {
protected:
int studentID;
public:
student(int id);
void print();
};
class teacher : public person {
protected:
int deptID;
public:
teacher(int d);
void print();
};
Virtual Functions Example 2
void person::print() {
cout << name << “ “ << phone << endl;
}
void student::print() {
cout << “Student” << endl;
cout << “ID: “ << studentID << endl;
cout << name << endl << phone << endl;
}
void teacher::print() {
cout << “Teacher” << endl;
cout << “Dept: “ << deptID << endl;
cout << name << endl << phone << endl;
}
Virtual Functions Example 3
void main() {
int x;
person **array = new person*[3];
array[0] = new student(“Joe”, “555-1234”, 3976);
array[1] = new teacher(“Daisy”, “555-8909”, 203);
array[2] = new person(“Mandy”, “555-3782”);
for (x = 0; x < 3; x++) array[x]->print();
}
More Virtual Functions
• Without virtual functions, only the base class print()
function would be called
• This is because all the pointers are of the base type
• WITH virtual functions, the correct print function is called for
each member of the array
– array[0]->print() calls student::print()
– array[1]->print() calls teacher::print()
– array[2]->print() calls person::print()
What does this mean?
• It means that you don’t necessarily have to know the
EXACT type of the object you’re dealing with
• You only have to know it’s base type
• Base classes & base class interfaces written by someone
else long ago can work with new classes you write
Abstract Base Classes
• Sometimes you will NEVER WANT TO instantiate an object
of the base class.
• E.g., doesn’t make sense to make a shape object
– Only a square object, a circle object, or some other derived
object actually makes sense…
• Can make the class abstract so that future programmers
cannot create a base class object either
Implementing
Pure Virtual Functions
• How do you make a base class abstract?
• Make at least one of its member functions PURE
VIRTUAL
• Functions should be pure virtual if information is needed
from the derived class for any valid implementation
– a shape’s area function depends on what type of shape it is
Review of Pure Virtual Functions
• Pure virtual functions are defined in the class declaration by:
virtual returnType functionName(arglist) const = 0;
• So for the shape area function example, we’d have in the
shape class:
virtual float area() const = 0;
• There is NO IMPLEMENTATION of pure virtual functions in
the base class, just the declaration
Virtual Destructors
• Why should destructors be virtual if a base class has any
virtual functions?
• Derived objects will likely be accessed by base pointers
• If you “delete” a base pointer without a virtual destructor,
it will only call the base destructor
• If virtual, however, it will call the correct derived destructor,
then the base destructor
Example
#include <iostream.h>
class base {
public:
virtual void vfunc() { cout<<“This is the base vfunc().\n”; }
};
class derived1 : public base {
public:
virtual void vfunc() { cout<<“This is a derived function\n”;}
};
class derived2 : public base {
public:
virtual void vfunc() { cout<<“So is this one.\n”; }
};
Example in Action
int main() {
base* p;
base b;
derived1 d1;
derived2 d2;
A pointer to the parent class
p=&b;
p->vfunc();
p=&d1;
p->vfunc();
p=&d2;
p->vfunc();
}
OUTPUT:
This is a base vfunc().
This is a derived function.
So is this one.
Other Examples of Polymorphism
• Queue of jobs to do
– Homework
– Cleaning
– Cooking
• Linked list of classes
– Lectures
– Labs
– Discussion sections
Conclusion for Virtual Functions
• A virtual function is a member function that is declared
within a base class and redefined by a derived class.
• Its looks just like a normal function but has the keyword
virtual preceding it.
• So the virtual function defines the form of the interface.
• The derived class redefines it and implements its
operation as it relates specifically to it.
Why Virtual Functions are Useful
(concluded)
• So you can just use virtual functions as you would any
other function.
• However what makes them so implortant is how they
behave when accessed by a pointer.
• When a base-class pointer points to a derived object that
contains a virtual function, C++ decides which version of
that function to call – based on the type of object pointed
to.
• This is all processed at run-time.
Conclusion of Abstract Classes
• A class that contains at least one pure virtual function is said to
be abstract – it has a virtual function in it that has no definition at
all.
• Because of this, no objects of the abstract class can be created.
• It is an incomplete type – a foundation for derived classes.
• However you can still create a pointer to an abstract class.
Conclusion of Polymorphism
• An object can take many forms.
– Method overloading is one type of polymorphism.
– Object polymorphism treats specialized objects as if they are
instances of a more general type.
More on Factoring to the Base Class
•
Factor common characteristics of multiple classes up
into a base class.
– HWall and VWall classes have similar characteristics and
methods.
– Factor commonalities to a Wall class
– Override some methods to specialize the HWall and VWall classes
Conclusion of Abstract Base Classes
•
The classes describe what all derived classes have in
common.
– Not instantiated (causes an exception)
– Use the abstract keyword when defining abstract base classes
and methods
Conclusion For Abstract Methods
– Abstract methods are not implemented.
– Derived classes must provide method implementation.
Topic For Next Week
• Template
• Assignment:
Read chapter 9 of C++Essentials.pdf, and then do the
following exercise:
Define a swap function template for swapping two
objects of the same type!
39
Download