Object-Oriented Programming in C++

advertisement
Object-Oriented Programming
in C++
Lecture 7
Polymorphism
Introduction
Last lecture we
•reviewed the concept of inheritance
•discussed how to implement inheritance in
C++
This lecture we will
•introduce polymorphism
•explain virtual and pure virtual functions
•learn how to use polymorphism in C++
programs
Polymorphism Vehicle
• many forms
• Greek
+move()
– "poly" – many
– "morph" form
LandVehicl
Airplane
• the same method can
be called on different
e
+move()
objects
+move()
• they may respond to it
in different ways
• all Vehicles have a
Car
Truck
move method
• Cars and Truck drive
• Airplanes fly
Polymorphism example
• see handout for implementation of Vehicle class hierarchy
#include "Vehicle.h"
int main(){
Vehicle v ("Transporter 54");
Airplane a("Tornado 2431", 14);
LandVehicle lv("My wheels");
Car c("Ford Anglia 22");
Truck t("Red pickup");
v.move();
a.move();
lv.move();
c.move();
t.move();
}
Output
Vehicle constructor
Vehicle constructor
Airplane constructor
Vehicle constructor
Land vehicle constructor
Vechicle constructor
Land vehicle constructor
Car constructor
Vechicle constructor
Land vehicle constructor
Truck constructor
Vehicle Transporter 54
moving
Airplane Tornado 2431
flying
Land Vehicle My wheels
driving
Land Vehicle Ford Anglia
22 driving
Land Vehicle Red pickup
driving
Which version of move is called
• in the previous example, the version of
move to be called was determined at
compile time
– depends on the object type
– for Airplane a, the Airplane version of move
– for Car c, the Vehicle version of move
• what about a situation where the type is
not known at compile time?
#include "Vehicle.h"
void moveVehicle(Vehicle * v) {
v->move();
}
int main(){
Vehicle v ("Transporter 54");
Airplane a("Tornado 2431", 14);
LandVehicle lv("My wheels");
Car c("Ford Anglia 22");
Truck t("Red pickup");
moveVehicle(&v);
moveVehicle(&a);
moveVehicle(&lv);
moveVehicle(&c);
moveVehicle(&t);
}
Output
….
Vehicle Transporter
54 moving
Vehicle Tornado 2431
moving
Vehicle My wheels
moving
Vehicle Ford Anglia
22 moving
Vehicle Red pickup
moving
• the moveVehicle
method takes a pointer to
any Vehicle object
• which could be any
subtype of Vehicle
• however, the move
method to call is
determined at compile
time
– Vehicle version
• all vehicles move the
same way
Polymorphic behaviour
• to get polymorphic behaviour, we would like the version
of move() to be determined at run-time
• if moveVehicle is sent an Airplane object, it should
get it to fly
• do this by using the virtual keyword in the first (base
class) declaration of the polymorphic method
class Vehicle {
protected:
string name;
public:
// other members
virtual void move() { cout << "Vehicle "
<< name << " moving" << endl; }
};
• now it works
Polymorphic output
Vehicle Transporter 54 moving
Airplane Tornado 2431 flying
Land Vehicle My wheels driving
Land Vehicle Ford Anglia 22 driving
Land Vehicle Red pickup driving
Polymorphism
• polymorphism allows us to use a pointer to
a derived type object wherever a pointer to
base type is expected
Car c("Ford Anglia 22");
Vehicle * v2 = &c;
v2->move();
Land Vehicle Ford Anglia 22 driving
Land Vehicle Ford Anglia 22 driving
Vehicle & v3 = c;
v3.move();
• only works for pointer and reference types
• they store an address – same size for all objects
This won't work
Airplane a("Tornado 2431", 14);
Vehicle v2 = a;
v2.move();
• trying to fit an airplane into a space meant
for any vehicle
• can call the move() method, but we've lost
the wingspan member variable
Virtual destructors
• constructors cannot be virtual
– the correct one is always called anyway
• destructors can be virtual
• you should specify a virtual destructor for
any class which is overridden
• so that the object is cleaned up correctly
• otherwise you might not deallocate all the
memory allocated to a subclass object
Pure virtual functions
• sometimes it is not sensible to implement a base
class virtual function
• how does a Vehicle move?
• a pure virtual function does not have an
implementation
• virtual void move() =0;
• the subclasses must implement it
• a class with a pure virtual function cannot be
instantiated
– if we made it virtual, how would it move?
• such a class is abstract
Comparison to Java
• in Java, all methods are virtual by default
• the keyword abstract is used to define
pure virtual functions
• a class containing an abstract method
must itself be abstract
• C++ is more flexible but can be confusing
– why have virtual and non-virtual functions?
Virtual functions
• using a virtual function has an overhead
• the correct method cannot be bound to a
method call at compile time
• it is determined at run-time by looking up
the correct method address in a table
• this takes up time and space
• if polymorphism is not being used, this is
expensive.
Summary
In this lecture we have:
•introduced polymorphism
•explained virtual and pure virtual functions
•learned how to use polymorphism in C++
programs
Download