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

C++ Abstract Classes

An abstract class is an unfinished blueprint that is meant to be extended, like a sketch others must complete. You cannot create one directly.
Syntax
cpp
class AbstractClass {
public:
  virtual return_type method_name() = 0;  // makes the class abstract
};

What is an Abstract Class?

An abstract class is any class that contains at least one pure virtual function.

You can never create a direct object of an abstract class, but you can still declare pointers and references to it, which is exactly how polymorphic code interacts with abstract types.

Example: What is an Abstract Class?

cpp
#include <iostream>

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

int main() {
	// Shape s; would fail to compile: Shape is abstract
	std::cout << "Cannot instantiate Shape directly" << std::endl;
	return 0;
}

Abstract Class as an Interface

Abstract classes function as interfaces: they specify which operations a derived class must support without dictating how those operations are implemented, letting each concrete subclass provide its own behavior behind a shared, predictable API.

Example: Abstract Class as an Interface

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;
}

Constructors in Abstract Classes

Even though you can't instantiate an abstract class directly, it's still allowed to have constructors — these run automatically as part of constructing any concrete derived class, setting up whatever base-level state the abstract class defines.

Example: Constructors in Abstract Classes

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:
	Shape() { std::cout << "Shape constructor runs" << std::endl; }
	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;
}

Abstract Class Arrays/Vectors

You can declare arrays or containers of abstract base class pointers, which is a powerful pattern for storing a mixed collection of different concrete subtypes and processing all of them uniformly through their shared abstract interface.

Example: Abstract Class Arrays/Vectors

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

// 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; }
};

class Square : public Shape {
public:
	void draw() override { std::cout << "Square" << std::endl; }
};

// Program execution starts in main()
int main() {
	// Create a vector named shapes (a resizable array)
	std::vector<Shape *> shapes = {new Circle(), new Square()};
	for (Shape *s : shapes) s->draw();
	return 0;
}

Concrete Classes vs Abstract Classes

Concrete classes implement every inherited pure virtual method and can be instantiated freely, while abstract classes deliberately defer some or all of that implementation and exist purely to define a shared outline for their descendants to fill in.

Example: Concrete Classes vs Abstract Classes

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;
}
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 instantiate an abstract class directly, which is a compile error.
  2. Not implementing all pure virtual functions, so the derived class stays abstract.
  3. Storing abstract objects by value in a vector instead of using pointers or smart pointers.

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.