Polymorphism and Virtual Functions
Reference: Chapter 15
Modern object-oriented (OO) languages provide 3 capabilities:
- encapsulation
- inheritance
- polymorphism
which can improve the design, structure and reusability of code.
Here, we'll explore in more detail how polymorphism can be used in C++.
What is polymorphism?
In programming languages, polymorphism means that some code or operations or objects behave differently in different contexts.
For example, the + (plus) operator in C++:
4 + 5 | integer addition |
3.14 + 2.0 | floating point addition |
s1 + "bar" | string concatenation |
This type of polymorphism is accomplished through operator overloading, but polymorphism is not limited to operators.
C++ actually has four kinds of polymorphism:
- Subtype polymorphism, also known as runtime polymorphism.
- Parametric polymorphism, also known as compile-time polymorphism.
- Ad-hoc polymorphism, also known as overloading.
- Coercion, also known as (implicit or explicit) casting.
More about these types: http://www.catonmat.net/blog/cpp-polymorphism/
A typical scenario of polymorphism in C++:
- There is an inheritance hierarchy.
- The first class that defines a virtual function is the base class of the hierarchy that uses dynamic binding for that function's name and signature.
- Each of the derived classes in the hierarchy must have a virtual function with the same name and signature.
- There is a pointer of the base class type, and that pointer is used to invoke virtual functions of derived classes.
The rest of this lecture will go through several examples as part of the code in week8 of the lecture code repository -- additional notes will be posted after lecture.
Compile time vs runtime binding
Compile-time binding is to associate a function's name with the entry point of the function at compile time. Example:
#include <iostream> void sayHi(); int main() { sayHi(); // the compiler binds any invocation of sayHi // to sayHi's entry point } void sayHi() { std::cout << "Hello, World!\n"; }
In C, only compile-time binding is provided. In C++, all non-virtual functions are bound at compile time.
Runtime binding (dynamic binding) is to associate a function's name with the entry point at runtime. C++ supports runtime binding through virtual functions.
Runtime polymorphism is thus implemented by virtual functions and the vtable runtime binding mechanism in C++. A class is called polymorphic if it contains virtual functions.
- Use compile-time binding when you are sure that any derived class will not want to override the function dynamically.
- Use run-time binding when the derived class may be able to provide a different implementation that should be selected at runtime.