0Pricing
C++ Academy · Lesson

Static Polymorphism

Avoid virtual call overhead.

Static Polymorphism is a free C++ Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Two Kinds of Polymorphism

C++ supports two flavors of polymorphism.

  • Dynamic: virtual functions resolved at runtime via vtable
  • Static: templates/CRTP resolved at compile time

Static polymorphism trades flexibility for speed.

The Cost of virtual

A virtual call requires an indirect jump through the vtable. The compiler usually cannot inline it, blocking many optimizations.

#include <iostream>

struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

struct Square : Shape {
    double s;
    Square(double x) : s(x) {}
    double area() const override { return s * s; }
};

int main() {
    Shape* p = new Square(3);
    std::cout << p->area() << "\n";
    delete p;
    return 0;
}

Static Dispatch with CRTP

With CRTP the base calls the derived method directly through a compile-time cast, so the compiler can inline everything.

#include <iostream>

template <typename T>
struct Shape {
    double area() const { return static_cast<const T*>(this)->area(); }
};

struct Square : Shape<Square> {
    double s;
    Square(double x) : s(x) {}
    double area() const { return s * s; }
};

int main() {
    Square sq(3);
    std::cout << sq.area() << "\n";
    return 0;
}

Forwarder Naming

When the base and derived both define area, give the base forwarder a distinct name like compute so it unambiguously calls into the derived implementation.

#include <iostream>

template <typename T>
struct Shape {
    double compute() const { return static_cast<const T*>(this)->area(); }
};

struct Circle : Shape<Circle> {
    double r;
    Circle(double x) : r(x) {}
    double area() const { return 3.14159 * r * r; }
};

int main() {
    Circle c(2);
    std::cout << c.compute() << "\n";
    return 0;
}

Templates as Static Polymorphism

Plain function templates are also static polymorphism: the same code works for any type providing the required interface (duck typing at compile time).

#include <iostream>

struct Dog { void speak() const { std::cout << "Woof\n"; } };
struct Cat { void speak() const { std::cout << "Meow\n"; } };

template <typename Animal>
void make_speak(const Animal& a) { a.speak(); }

int main() {
    make_speak(Dog{});
    make_speak(Cat{});
    return 0;
}

When the Type Is Known

Static polymorphism applies only when the concrete type is known at compile time. If you must store heterogeneous objects in one container and choose behavior at runtime, you still need virtual functions.

No Heterogeneous Containers

You cannot put Shape<Square> and Shape<Circle> in the same std::vector as a common base, because they are unrelated types. This is the central limitation of static polymorphism.

Performance Benefit

By inlining the dispatched call, the compiler can fold constants and eliminate function-call overhead entirely. In tight loops over a single known type, static polymorphism can be substantially faster.

#include <iostream>

template <typename T>
struct Op {
    int apply(int x) const { return static_cast<const T*>(this)->apply(x); }
};

struct Doubler : Op<Doubler> {
    int apply(int x) const { return x * 2; }
};

int main() {
    Doubler d;
    int sum = 0;
    for (int i = 0; i < 5; ++i) sum += d.apply(i);
    std::cout << sum << "\n";
    return 0;
}

Combining Both

You can use CRTP for the hot path and a thin virtual wrapper when type erasure is needed. This gives speed where it matters and flexibility where required.

Static Interface Checks

If a derived class forgets to implement the required method, the error appears at compile time when the base forwarder is instantiated, not at runtime.

#include <iostream>

template <typename T>
struct Greeter {
    void greet() const { static_cast<const T*>(this)->hello(); }
};

struct English : Greeter<English> {
    void hello() const { std::cout << "Hello\n"; }
};

int main() {
    English{}.greet();
    return 0;
}

Choosing the Right Tool

Use static polymorphism when:

  • The type is known at compile time
  • Performance is critical
  • You do not need a common runtime base type

Otherwise prefer virtual functions for clarity and flexibility.

Quick Check

Pick the key trade-off of static polymorphism.

Recap

You compared static and dynamic polymorphism.

  • Virtual = runtime dispatch, vtable, heterogeneous containers
  • CRTP/templates = compile-time dispatch, inlinable, faster
  • Static needs the type known at compile time
  • Choose based on flexibility vs performance needs

Frequently asked questions

Is the “Static Polymorphism” lesson free?

Yes — the full text of “Static Polymorphism” is free to read here on the web, and the C++ Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C++ Academy course, upgrade to CoddyKit PRO.

What will I learn in “Static Polymorphism”?

Avoid virtual call overhead. You practise C++ Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C++ Academy?

No prior experience is required. C++ Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Static Polymorphism” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C++ Academy lesson?

Yes. Every C++ Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. The CRTP Idiom
  2. Static Polymorphism
  3. Mixins with CRTP
  4. When to Use CRTP
← Back to C++ Academy