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

C++ Pure Virtual Functions

A pure virtual function is a promise with no body that child classes must fill in, like a job listing nobody has done yet. A class with one cannot be created by itself.
Syntax
cpp
class Base {
public:
  virtual return_type method_name() = 0;  // pure virtual
};

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

What is a Pure Virtual Function?

A pure virtual function is declared in a base class with no default implementation at all, using the syntax 'virtual void functionName() = 0;'.

It acts as a contract, forcing every concrete subclass to supply its own implementation before it can be instantiated.

Example: What is a Pure Virtual Function?

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() = 0;
};

// 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() {
	Circle c;
	c.draw();
	// Return 0 to signal that the program finished successfully
	return 0;
}

Implementing Pure Virtual Functions

Any concrete (non-abstract) child class is required to implement every pure virtual function it inherits; if it fails to override even one of them, that child class itself becomes abstract too and inherits the same restriction against being instantiated directly.

Example: Implementing Pure Virtual Functions

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() = 0;
};

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

// Program execution starts in main()
int main() {
	Square s;
	s.draw();
	// Return 0 to signal that the program finished successfully
	return 0;
}

Partial Implementation

If an intermediate class in a hierarchy inherits from an abstract class but doesn't override its pure virtual function, that intermediate class remains abstract as well — only a class further down the chain that finally provides the implementation becomes concrete and instantiable.

Example: Partial Implementation

cpp
#include <iostream>

class Shape {
public:
	virtual void draw() = 0;
	virtual void resize() = 0;
};

class PartialShape : public Shape {
public:
	void draw() override { std::cout << "Drawing" << std::endl; }
	// resize() not overridden: PartialShape is still abstract
};

class FullShape : public PartialShape {
public:
	void resize() override { std::cout << "Resizing" << std::endl; }
};

int main() {
	FullShape s;
	s.draw();
	s.resize();
	return 0;
}

Pure Virtual with Body

Somewhat surprisingly, a pure virtual function is allowed to have a function body in C++, even though it must still be overridden to make the class concrete.

That body must be defined outside the class definition, and derived classes can optionally call it explicitly as shared default logic.

Example: Pure Virtual with Body

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() = 0;
};

void Shape::draw() {
	// Print to the console with cout
	std::cout << "Default shape drawing logic" << std::endl;
}

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

// Program execution starts in main()
int main() {
	Circle c;
	c.draw();
	return 0;
}

Pure Virtual Destructors

You can declare a destructor as pure virtual, which forces the class to remain abstract, but you must still provide a body for it, since every destructor in the inheritance chain — including this one — will eventually be called when a derived object is destroyed.

Example: Pure Virtual Destructors

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 ~Shape() = 0;
};

Shape::~Shape() {
	// Print to the console with cout
	std::cout << "Shape destructor body" << std::endl;
}

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

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Shape *s = new Circle();
	delete s;
	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. Trying to create an object of a class that has a pure virtual function, which is a compile error.
  2. Not implementing every pure virtual function in the derived class, which leaves it abstract too.
  3. Writing virtual void f() {} = 0;, when the pure specifier is virtual void f() = 0;.

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.