Lesson content
Read, practise, then check your understanding
Polymorphism lets one operation work with different types. Compile-time polymorphism includes function overloading, operator overloading, and templates; the compiler chooses or generates code from static types. Runtime polymorphism uses virtual functions through a base pointer or reference.
#include <iostream>
#include <memory>
struct Shape {
virtual ~Shape() = default;
virtual double area() const = 0;
};
struct Square final : Shape {
double side;
explicit Square(double value) : side{value} {}
double area() const override { return side * side; }
};
std::unique_ptr<Shape> shape = std::make_unique<Square>(4.0);
std::cout << shape->area();
override asks the compiler to verify a real override. final can prevent further overriding or derivation. A polymorphic base destructor must be virtual if objects may be deleted through the base.
Slicing and alternatives
Copying a derived object into a base value discards the derived portion, called object slicing. Pass polymorphic objects by reference or pointer and express ownership explicitly. Virtual dispatch has an indirection cost and constrains data layout, but is often appropriate for open runtime families.
Templates provide static dispatch and can inline aggressively, but expose implementation in headers and may increase code size. std::variant is useful for a closed set of alternatives. Choose among virtual interfaces, templates, variants, and ordinary composition based on whether the type set is open, when selection occurs, and what ownership model is required.
Knowledge check
Answer every question correctly to complete this chapter.
0 of 10 checks passed
Your progress is saved on this device.