C++ Program for Opaque Pointer
Opaque pointers (or opaque types) in C++ are used to hide the implementation details of a data structure from the users of the interface. This technique is often used to achieve data encapsulation and information hiding, which are important principles of object-oriented programming. The main advantage of using opaque pointers is to provide a clear separation between the interface and the implementation, which leads to better modularity and maintainability of code.
Key Concepts
- Definition and Usage
An opaque pointer is a pointer to a data structure whose definition is hidden from the user. The user interacts with the pointer through a defined interface without needing to know the internal details of the data structure.
- Implementation
Typically involves defining an incomplete type in the public header and the complete type in the implementation file.
Let’s create a program to demonstrate the use of opaque pointers in C++. We will create a ‘Rectangle’ class with its implementation details hidden using an opaque pointer.
File: ‘Rectangle.h’ (Public Header)
#ifndef RECTANGLE_H
#define RECTANGLE_H
// Forward declaration of the RectangleImpl struct
struct RectangleImpl;
class Rectangle {
public:
// Constructor
Rectangle(int length, int width);
// Destructor
~Rectangle();
// Member function to set dimensions
void setDimensions(int length, int width);
// Member function to calculate area
int area() const;
// Member function to print dimensions
void printDimensions() const;
private:
RectangleImpl* pImpl; // Opaque pointer to implementation
};
#endif // RECTANGLE_H
File: ‘Rectangle.cpp’ (Implementation)
#include <iostream>
#include “Rectangle.h”
using namespace std;
// Definition of the RectangleImpl struct
struct RectangleImpl {
int length;
int width;
RectangleImpl(int l, int w) : length(l), width(w) {}
};
Rectangle::Rectangle(int length, int width)
: pImpl(new RectangleImpl(length, width)) {}
Rectangle::~Rectangle() {
delete pImpl;
}
void Rectangle::setDimensions(int length, int width) {
pImpl->length = length;
pImpl->width = width;
}
int Rectangle::area() const {
return pImpl->length * pImpl->width;
}
void Rectangle::printDimensions() const {
cout << “Length: ” << pImpl->length << “, Width: ” << pImpl->width << endl;
}
File: ‘main.cpp’ (Client Code)
#include “Rectangle.h”
int main() {
// Create an object of Rectangle using the constructor
Rectangle rect(10, 5);
rect.printDimensions();
// Set new dimensions
rect.setDimensions(15, 10);
rect.printDimensions();
// Calculate and print the area
cout << “Area: ” << rect.area() << endl;
return 0;
}
Explanation of the Program
Public Header (‘Rectangle.h’)
- Forward Declaration: Forward declares the ‘RectangleImpl’ struct, making it known to the ‘Rectangle’ class without revealing its implementation.
- Rectangle Class: The ‘Rectangle’ class contains a private member ‘pImpl’, which is a pointer to ‘RectangleImpl’.
Implementation File (‘Rectangle.cpp’)
Defines the actual structure of ‘RectangleImpl’, which contains the ‘length’ and ‘width’
- Constructor and Destructor: The constructor initializes ‘pImpl’ by creating a new ‘RectangleImpl’ object, and the destructor deletes ‘pImpl’ to free the allocated memory.
- Member Functions: These functions manipulate the ‘RectangleImpl’ object through the opaque pointer ‘pImpl’.
Client Code (‘main.cpp’)
The client code interacts with the ‘Rectangle’ class without needing to know about ‘RectangleImpl’. The client can create a ‘Rectangle’ object, set its dimensions, and calculate its area using the public interface.