
- C++ Home
- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Hello World
- C++ Omitting Namespace
- C++ Tokens
- C++ Constants/Literals
- C++ Keywords
- C++ Identifiers
- C++ Data Types
- C++ Numeric Data Types
- C++ Character Data Type
- C++ Boolean Data Type
- C++ Variable Types
- C++ Variable Scope
- C++ Multiple Variables
- C++ Input Output Operations
- C++ Basic Input/Output
- C++ Cin
- C++ Cout
- C++ Manipulators
- Type System & Data Representation
- C++ Modifier Types
- C++ Storage Classes
- C++ Constexpr Specifier
- C++ Numbers
- C++ Enumeration
- C++ Enum Class
- C++ References
- C++ Date & Time
- C++ Operators
- C++ Operators
- C++ Arithmetic Operators
- C++ Relational Operators
- C++ Logical Operators
- C++ Bitwise Operators
- C++ Assignment Operators
- C++ sizeof Operator
- C++ Conditional Operator
- C++ Comma Operator
- C++ Member Operators
- C++ Casting Operators
- C++ Pointer Operators
- C++ Operators Precedence
- C++ Unary Operators
- C++ Scope Resolution Operator
- C++ Control Statements
- C++ Decision Making
- C++ if Statement
- C++ if else Statement
- C++ Nested if Statements
- C++ switch Statement
- C++ Nested switch Statements
- C++ Loop Types
- C++ while Loop
- C++ for Loop
- C++ do while Loop
- C++ Foreach Loop
- C++ Nested Loops
- C++ Jump Statements
- C++ break Statement
- C++ continue Statement
- C++ goto Statement
- C++ Return Values
- C++ Strings
- C++ Strings
- C++ Loop Through a String
- C++ String Length
- C++ String Concatenation
- C++ String Comparison
- C++ Functions
- C++ Functions
- C++ Multiple Function Parameters
- C++ Recursive Function
- C++ Function Overloading
- C++ Function Overriding
- C++ Default Arguments
- C++ Arrays
- C++ Arrays
- C++ Multidimensional Arrays
- C++ Pointer to an Array
- C++ Passing Arrays to Functions
- C++ Return Array from Functions
- C++ Array Decay
- C++ Structure & Union
- C++ Structures
- C++ Unions
- C++ Class and Objects
- C++ Object Oriented
- C++ Classes & Objects
- C++ Class Member Functions
- C++ Class Access Modifiers
- C++ Static Class Members
- C++ Static Data Members
- C++ Static Member Function
- C++ Inline Functions
- C++ this Pointer
- C++ Friend Functions
- C++ Pointer to Classes
- C++ Constructors
- C++ Constructor & Destructor
- C++ Default Constructors
- C++ Parameterized Constructors
- C++ Copy Constructor
- C++ Constructor Overloading
- C++ Constructor with Default Arguments
- C++ Delegating Constructors
- C++ Constructor Initialization List
- C++ Dynamic Initialization Using Constructors
- C++ Destructors
- C++ Virtual Destructor
- C++ Inheritance
- C++ Inheritance
- C++ Multiple Inheritance
- C++ Multilevel Inheritance
- C++ Object-oriented
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Virtual Function
- C++ Pure Virtual Functions & Abstract Classes
- C++ Override Specifiers
- C++ Final Specifiers
- C++ Design Patterns
- C++ Creational Design Patterns
- C++ Singleton Design Pattern
- C++ Factory Method Design Pattern
- C++ Abstract Factory Pattern
- C++ Prototype Design Pattern
- C++ Structural Design Patterns
- C++ File Handling
- C++ Files and Streams
- C++ Reading From File
- C++ Advanced
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Socket Programming
- C++ Concurrency
- C++ Advanced Concepts
- C++ Lambda Expression
- C++ nullptr
- C++ unordered_multiset
- C++ Structural Design Patterns
- C++ Adapter Pattern
- C++ Bridge Pattern
- C++ Composite Pattern
- C++ Decorator Pattern
Adapter Design Pattern in C++
Adapter is a part of Structural Design Patterns. Adapter pattern works like a bridge between two incompatible interfaces. It involves a single class which is responsible for joining the functionalities of interfaces that are independent and not compatible with each other. This pattern is also known as Wrapper.
Adapter works as a middleman of two things that do not go along together. For example, your laptop has a USB port and you have a SD card that you want to connect to your laptop. Here, USB and SD are two incompatible interfaces. To make them compatible, you need an adapter that can convert SD to USB. So, in the market you will find SD to USB adapter. This adapter will have SD port on one side and USB port on another side. You can connect your SD card to the adapter and then connect the adapter to your laptop's USB port. Now, you can access your SD card data through your laptop.
The Adapter pattern is used when you want to use some existing code, but its interface does not match the one you need. In such cases, you create an adapter class that implements the interface you want and translates calls to the existing code.

In the above image, we have a Phone which does not have headphone jack. So, we cannot connect our headphones directly to the Phone. To solve this problem, we use an Adapter which has a lightning connector on one side and a headphone jack on another side. We can connect the adapter to the Phone and then connect our headphones to the adapter. This way, we can use our headphones with the Phone. This is an example of the Adapter pattern in real life.
Types of Adapter Pattern
There are two types of Adapter pattern −
- Class Adapter Pattern − In this, we use multiple inheritance to adapt one interface to another.
- Object Adapter Pattern − We use composition to adapt one interface to another.
Let's understand in detail how these two types of adapter patterns work.
Class Adapter Pattern in C++
We use Class Adapter Pattern when we want to adopt one interface to another using multiple inheritance. In this pattern, the adapter class inherits from both the target interface and the adaptee class. This way, the adapter can override methods from the target interface and use methods from the adaptee class to provide the functionality we want.
Steps to implement Class Adapter Pattern are as follows −

Example of Class Adapter Pattern in C++
In this example, a modern music player wants us to play MP3 files, but we only have an old cassette player. Using the Class Adapter Pattern, we adapt the old cassette player so it can be used as an MP3 player.
#include <iostream> using namespace std; // Target interface class IMediaPlayer { public: virtual void playMP3(string filename) = 0; }; // Adaptee class class OldCassettePlayer { public: void playCassette(string tape) { cout << "Playing cassette tape: " << tape << endl; } }; // Adapter class class CassetteToMP3Adapter : public IMediaPlayer, private OldCassettePlayer { public: void playMP3(string filename) override { // Convert MP3 filename to cassette tape format string tape = filename + ".cassette"; playCassette(tape); // Use the adaptee's method } }; // Client code int main() { IMediaPlayer* player = new CassetteToMP3Adapter(); player->playMP3("MyFavoriteSong"); delete player; return 0; }
Following is the output of the above code −
Playing cassette tape: MyFavoriteSong.cassette
In this example, the IMediaPlayer
interface is the target interface that expects an MP3 player. The OldCassettePlayer
class is the adaptee that can only play cassette tapes. The CassetteToMP3Adapter
class inherits from both the target interface and the adaptee class, allowing it to adapt the cassette player to work as an MP3 player.
Object Adapter Pattern in C++
We use Object Adapter Pattern when we want to adopt one interface to another using composition. In this pattern, the adapter class contains an instance of the adaptee class and implements the target interface. The adapter class translates calls from the target interface to the adaptee class.
Steps to implement Object Adapter Pattern are as follows:
Steps are almost same as Class Adapter Pattern except that in Object Adapter Pattern we use composition (has-a relationship) instead of inheritance (is-a relationship).

Example of Object Adapter Pattern in C++
Now, Let's implement the same example of music player using Object Adapter Pattern.
#include <iostream> using namespace std; // Target interface class IMediaPlayer { public: virtual void playMP3(string filename) = 0; }; // Adaptee class class OldCassettePlayer { public: void playCassette(string tape) { cout << "Playing cassette tape: " << tape << endl; } }; // Adapter class class CassetteToMP3Adapter : public IMediaPlayer { private: OldCassettePlayer* cassettePlayer; // Composition public: CassetteToMP3Adapter(OldCassettePlayer* player) { this->cassettePlayer = player; } void playMP3(string filename) override { // Convert MP3 filename to cassette tape format string tape = filename + ".cassette"; cassettePlayer->playCassette(tape); // Use the adaptee's method } }; // Client code int main() { OldCassettePlayer* oldPlayer = new OldCassettePlayer(); IMediaPlayer* player = new CassetteToMP3Adapter(oldPlayer); player->playMP3("MyFavoriteSong"); delete player; delete oldPlayer; return 0; }
Following is the output of the above code −
Playing cassette tape: MyFavoriteSong.cassette
In this example, the IMediaPlayer
interface is the target interface that expects an MP3 player. The OldCassettePlayer
class is the adaptee that can only play cassette tapes. The CassetteToMP3Adapter
class implements the target interface and contains an instance of the adaptee class, which allows it to adapt the cassette player to work as an MP3 player.
When to use Adapter Pattern?
You should consider using the Adapter pattern in the following scenarios −
- When you want to use an existing class, but its interface does not match the one you need.
- To create a reusable class that can work with different interfaces.
- While integrating third-party libraries or legacy code that have incompatible interfaces.
- Decoupling the client code from the implementation details of the adaptee class.
- When you want to provide a standard interface for a set of classes with different interfaces.
Real World Applications of Adapter Pattern
Some real-world applications in software development where the Adapter pattern is commonly used are shown in the below image −

Conclusion
This chapter was about the Adapter design pattern. Itâs a structural pattern that helps in making incompatible things work together. We looked at both the Class Adapter and Object Adapter with C++ examples. The Adapter pattern is very useful when working with old code or third-party libraries that donât match our interface. In short, it makes things work together that normally wouldnât.