INTRO TO COMPUTER SCIENCE II
POLYMORPHISM (CONT.)
CS162
Last time…
Polymorphism
Virtual functions
2 specifiers that can be used
Last time…
Polymorphism
When a call to a member function executes different code depending on the
type of object that invokes the function Virtual functions
Special type of function that resolves to the most derived version of the function that exists between the base and derived class
2 specifiers that can be used: override & final
//in animal.h
virtual string get_name();
virtual void make_noise(int);
//in monkey.h
string get_name() override;
void make_noise(int) final;
Abstract Polymorphism
Abstract function (pure virtual function)
No definition in the base class, but child classes need to define it or you’ll get an error when you try to create a derived object
virtual void move_forward(int) = 0;
Abstract class
Any class that has one or more pure virtual
An abstract class object cannot be instantiated
But you can use pointers & references to abstract class types
prog.cpp:19:9: error: cannot declare variable ‘m1’ to be of abstract type ‘Monkey’
Monkey m1(“Curious George”);
In file included from prog.cpp:3:0:
monkey.h:12:7: note: because the following virtual functions are pure within Monkey’:
class Monkey : public Animal {
In file included from prog.cpp:2:0:
animal.h:25:18: note: virtual void Animal::move_forward(int)
virtual void move_forward(int) = 0;
prog.cpp: In function ‘int main()’:
prog.cpp:15:9: error: cannot declare variable ‘a1’ to be of abstract type ‘Animal’
Animal a1(“Curious George”);
In file included from prog.cpp:2:0:
animal.h:10:7: note: because the following virtual functions are pure within Animal’:
class Animal {
animal.h:25:18: note: virtual void Animal::move_forward(int) virtual void move_forward(int) = 0;
functions
Interface Classes
A class with NO member variables, and where ALL of the functions are pure virtual/abstract
Useful when you want to define functionality derived classes must implement, but leave the details up to the derived class
class Shape { public:
virtual ~Shape();
virtual void move_x(distance x) = 0; virtual void move_y(distance y) = 0; virtual float area() = 0
//…
};
class Rectangle : public Shape { public:
virtual ~Rectangle(); void move_x(distance x); void move_y(distance y); float area();
private:
float width; float height; //…
};
No keyword in C++, just how you set it up
Inheritance & Polymorphism
Things that are not inherited Constructors
Destructors
friends
Whenever you are dealing with inheritance, make any explicit destructors virtual
Memory leaks if you delete a base class pointer pointing to a derived object
virtual ~Base(); virtual ~Derived();
Vocabulary – Binding
Binding
The process used to convert identifiers into addresses (such as variables and function names)
Early binding/static binding
The default behavior in C++. A function call always executes the same version of code.
The compiler is able to directly link the identifier name with an address Late binding/dynamic binding
Used when the type of object is evaluated at runtime. The compiler generated code will check to determine the object type and then execute the correct version of code
This is what allows C++ to support polymorphism (using the virtual keyword) Slightly less efficient, but more flexible
Inheritance & Objects
Recall that inheritance involves base classes and derived classes
In some cases, you might want to convert objects into different types
Let’s consider the hierarchy shown here
Animal
name, age make_noise() get_name()
Monkey
longest_jump get_name() make_noise()
Sea Otter
maximum_length, swim_speed make_noise()
swim()
Teal Sea
Otter
make_noise() swim()
Red Sea
Otter
make_noise() swim()
Object Slicing
What if we want to convert objects into different types?
Say, convert a Red_Sea_Otter object into an Animal so that we can put it in array with other Animals
Object slicing is the assigning of a Derived class object to a Base class object
“lose” any member variables that were specific to the Derived class
Won’t be able to access derived functions
Derived d;
Base b = d;
//example of object
slicing
Red_Sea_Otter rso;
Animal a1 = rso;
//a1 has now “lost” any
member variables specific
to Red_Sea_Otter
Using pointers instead
Pointers and polymorphism allow us to treat an object as a different type without permanently losing data
Create an array of Animal pointers instead of storing Animal objects
Animal* array[2];
Monkey m1;
Red_Sea_Otter rso;
array[0] = &m1;
array[1] = &rso;
for (int i=0; i<2; i++;)
array[i]->make_noise();
Animal Monkey
Sea Otter
Teal Sea Otter
Red Sea Otter
One detail…
It was easy to convert a Red_Sea_Otter pointer into an Animal pointer What about going in the opposite direction?
Red_Sea_Otter rso;
Animal* a_ptr = &rso;
//a_ptr is an Animal pointer
that points to a Red_Sea_Otter
//now attempt to convert this to
a Red_Sea_Otter pointer…
Red_Sea_Otter* r_ptr = a_ptr
prog.cpp: In function ‘int main()’:
prog.cpp:24:25: error: invalid conversion from ‘Animal*’ to ‘Red_Sea_Otter*’ [-fpermissive]
Red_Sea_Otter* r_ptr = a_ptr;
Static Object Casting
Operator used for converting between datatypes
Only works if base pointer actually points to the correct derived object and not
some other class
Doesn’t allow us to determine if pointer is actually valid
Doesn’t work if you have an array of pointers to random animals
If you accidentally try to cast a Monkey* into a Red_Sea_Otter*…bad things happen
Red_Sea_Otter rso;
Animal* aptr = &rso;
Red_Sea_Otter* r_ptr = static_cast
r_ptr->swim(4);
// if a_ptr was not pointing to a Red_Sea_Otter, the cast
// will fail silently! (Causing a SEGFAULT later!)
Dynamic Casting
Operator used for converting base pointers to derived pointers
Useful when you don’t know what the type of the object is
You have an animal pointer, but don’t know what type of animal
Red_Sea_Otter rso;
Red_Sea_Otter* tmp;
Animal* aptr = &rso;
tmp = dynamic_cast
if (tmp != nullptr){
tmp->swim(12);
} else {
} cout << “Red_Sea_Otter cast error” << endl;
Cast is verified at runtime
If the cast was successful, you get a valid
pointer
If unsuccessful, you get a nullptr
Also works with references
Let’s look at some code...
Animals and Monkeys and Sea Otters oh my!
Animal
name, age make_noise() get_name()
Monkey
longest_jump get_name() make_noise()
Sea Otter
maximum_length, swim_speed make_noise()
swim()
Teal Sea
Otter
make_noise() swim()
Red Sea
Otter
make_noise() swim()