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

C++ Abstract Classes

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 <iostream>

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

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

int main() {
	Circle c;
	c.draw();
	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 <iostream>

class Shape {
public:
	Shape() { std::cout << "Shape constructor runs" << std::endl; }
	virtual void draw() = 0;
};

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

int main() {
	Circle c;
	c.draw();
	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 <iostream>
#include <vector>

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

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

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

int main() {
	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 <iostream>

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

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

int main() {
	Circle c;
	c.draw();
	return 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.