← Back to C++ Course | Chapter 10: Polymorphism & Abstraction | Lesson 1 of 11

C++ Polymorphism Introduction

Polymorphism means one command can work in different ways depending on the object, like speak making a dog bark and a cat meow. You can treat different things the same way.
Syntax
cpp
class Base {
public:
  virtual void method_name() { }
};

class Derived : public Base {
public:
  void method_name() override { }
};

What is Polymorphism?

Polymorphism, literally 'many forms', lets a single action be carried out differently depending on the actual type of the object it's performed on, so the same function call can produce different behavior for different kinds of objects without the caller needing to know which kind it has.

Example: What is Polymorphism?

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual void speak() { std::cout << "..." << std::endl; }
};

// Define the type Dog
class Dog : public Animal {
// Members below can be accessed from outside the class
public:
	void speak() override { std::cout << "Woof" << std::endl; }
};

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Animal *a = new Dog();
	a->speak();
	// Free the heap memory with delete
	delete a;
	return 0;
}

Types of Polymorphism

C++ supports both static (compile-time) polymorphism, achieved through function and operator overloading, and dynamic (runtime) polymorphism, achieved through virtual functions — the two differ in when the decision about which function to call actually gets made.

Example: Types of Polymorphism

cpp
// Include std::cout and std::cin
#include <iostream>

void show(int x) { std::cout << "int: " << x << std::endl; }
void show(double x) { std::cout << "double: " << x << std::endl; }

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual void speak() { std::cout << "Animal" << std::endl; }
};

// Program execution starts in main()
int main() {
	show(5);
	show(5.5);
	Animal a;
	a.speak();
	// Return 0 to signal that the program finished successfully
	return 0;
}

Compile-Time Polymorphism

Compile-time polymorphism is resolved entirely by the compiler before the program ever runs, based purely on function names and argument types, which makes it essentially free at runtime since there's no decision left to make while the program executes.

Example: Compile-Time Polymorphism

cpp
// Include std::cout and std::cin
#include <iostream>

int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }

// Program execution starts in main()
int main() {
	// Print to the console with cout
	std::cout << add(2, 3) << std::endl;
	// Print to the console with cout
	std::cout << add(2.5, 3.5) << std::endl;
	// Return 0 to signal that the program finished successfully
	return 0;
}

Runtime Polymorphism Concept

Runtime polymorphism lets you write code against a parent pointer or reference while the actual method that executes is determined dynamically, based on the real (derived) type of the object the pointer happens to be pointing at when the call occurs.

Example: Runtime Polymorphism Concept

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Shape
class Shape {
// Members below can be accessed from outside the class
public:
	virtual void draw() { std::cout << "Shape" << std::endl; }
};

// Define the type Circle
class Circle : public Shape {
// Members below can be accessed from outside the class
public:
	void draw() override { std::cout << "Circle" << std::endl; }
};

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Shape *s = new Circle();
	s->draw();
	// Free the heap memory with delete
	delete s;
	return 0;
}

Benefits of Polymorphism

Polymorphism is what makes object-oriented code extensible: you can add entirely new derived classes later without touching a single line of the existing code that already works through base class pointers, since that code never needed to know about specific subtypes in the first place.

Example: Benefits of Polymorphism

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Shape
class Shape {
// Members below can be accessed from outside the class
public:
	virtual void draw() { std::cout << "Shape" << std::endl; }
};

// Define the type Triangle
class Triangle : public Shape {
// Members below can be accessed from outside the class
public:
	void draw() override { std::cout << "Triangle" << std::endl; }
};

void render(Shape *s) { s->draw(); }

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Shape *t = new Triangle();
	render(t);
	// Free the heap memory with delete
	delete t;
	return 0;
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting virtual on the base method, so the base version always runs through base pointers.
  2. Confusing overloading (same name, different parameters) with overriding (same signature in a derived class).
  3. Calling the method on a base object instead of a base pointer or reference and expecting polymorphic behavior.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.