C++ Data Abstraction
Data abstraction refers to providing only essential information to the outside world while hiding the background details, i.e., it represents only the necessary information without revealing the details.
Data abstraction is a programming (design) technique that relies on the separation of interface and implementation.
Let's take a real-life example, like a television, where you can turn it on and off, switch channels, adjust the volume, add external components (like speakers, VCRs, DVD players), but you don't know the internal details of how it receives signals through cables, converts signals, and finally displays them on the screen.
Thus, we can say that the television separates its internal implementation from its external interface, and you don't need to know its internal workings; you can control the TV directly through its external interface (like the power button, remote control, volume controller).
Now, getting back to C++ programming, C++ classes provide the possibility for data abstraction. They offer many public methods to manipulate the data of the object, meaning that the outside world doesn't actually know the internal implementation of the class.
For example, your program can call the sort() function without needing to know the algorithm used to sort the data within the function. In fact, the underlying implementation of the sorting function may vary between library versions, but as long as the interface remains the same, the function call will work as usual.
In C++, we use classes to define our own abstract data types (ADTs). You can use the cout object of the iostream class to output data to the standard output, as shown below:
Example
#include <iostream>
using namespace std;
int main()
{
cout << "Hello C++" << endl;
return 0;
}
Here, you don't need to understand how cout displays text on the user's screen. You only need to know the public interface, and the underlying implementation of cout can change freely.
Access Labels Enforce Abstraction
In C++, we use access labels to define the abstract interface of a class. A class can contain zero or more access labels:
Members defined with a public label are accessible to all parts of the program. The data abstraction view of a type is defined by its public members.
Members defined with a private label are not accessible to code that uses the class. The private section hides the implementation details from the code that uses the type.
There is no limit to the number of times an access label can appear. Each access label specifies the access level of the subsequent member definitions. The specified access level remains in effect until the next access label is encountered or the closing right brace of the class body is encountered.
Benefits of Data Abstraction
Data abstraction offers two important advantages:
The internal workings of a class are protected from inadvertent user-level errors that could corrupt the object's state.
Class implementations may change over time to meet evolving requirements or bug reports without requiring changes to user-level code.
If data members are defined in the private section of the class, the author of the class can freely change the data. If an implementation changes, only the class code needs to be examined to see what impact it may have. If data is public, any function that directly accesses the old representation's data members could be affected.
Example of Data Abstraction
Any C++ program with public and private members in a class can serve as an example of data abstraction. Consider the following example:
Example
#include <iostream>
using namespace std;
class Adder {
public:
// Constructor
Adder(int i = 0)
{
total = i;
}
// Interface to outside world
void addNum(int number)
{
total += number;
}
// Interface to outside world
int getTotal()
{
return total;
};
private:
// Hidden data from outside world
int total;
};
int main()
{
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total 60
The class above adds numbers and returns the sum. The public members addNum and getTotal are the interfaces to the outside world, and users need to know them to use the class. The private member total is something that the user doesn't need to know but is essential for the class to work properly.
Design Strategy
Abstraction separates code into interface and implementation. Therefore, when designing components, it's crucial to keep the interface independent of the implementation so that changes to the underlying implementation won't affect the interface.
In this case, the interface remains unchanged regardless of any changes to the program that uses the interface, and only the latest implementation needs to be recompiled.