Encapsulation in C++

Encapsulation in C++

With C++ we achieve the functionality to wrap data and functions inside as a single form and keep them safe from outside world and achieve data hiding from and make the code more secure from unauthorised access.

encapsulation

Data Abstraction –

Is essentially hiding the implementation details and only giving methods to interact with the system without knowing what exactly is happening in the backend code.

Encapsulation –

Encapsulation is, however, different. You wrap and bind all related data together in a single form.

Sort of like capsuling / binding it together.

Imagine if the car fails and the engine, battery system, clutching system and brake system etc are scattered all over the car (Rather than being hosted together in the front)

The mechanic will face a hard time figuring out what is wrong and will have to open the whole car open and it will take a lot more time for him to figure out what’s wrong.

Why do people get confused between Encapsulation and Data Abstraction?

With the help of encapsulation in a way we also achieve data abstraction, which is why people think that they are one and the same thing.

  • Yes, while doing encapsulation i.e. grouping into single units.
  • We simultaneously use access modifiers which directly help in hiding the data and managing its good architecture at the same time.

How Encapsulation is achieved in C++

Encapsulation is a state of binding/wrapping related data or code in one place.

In C++, we achieve this with classes by bundling all data members and member functions within a single class as shown below –

// all the required data members & member functions
// are wrapped together in a single class
// hence encapsulation is achieved below
// C++ was designed to help achieve encapsulation by default
class Rect {
  public:
    int len;
    int breadth;

    int calculateArea() {
      return len * breadth;
    }
};

Full Program for Above

Run
#include <iostream>
using namespace std;

class Rect {
  public:
    int len;
    int breadth;

    int calculateArea() {
      return len * breadth;
    }
};

int main(){
    
    Rect obj;
    
    obj.len = 10;
    obj.breadth = 20;
    
    cout << "Area: " << obj.calculateArea();
}

Output

Area: 200

Issues with Above Program & How Data Abstraction Solves it

We are able to directly access the variables length and breadth. Imagine if they were for User class and variables were username and password.

We need to create a protective interface, this is where data abstraction helps us.

We use access specifiers in C++ to achieve Data Abstraction.

Let us have a look at the example below to understand more about it –

  • Example 1: Shows how abstraction works using getters and setters
  • Example 2: Shows how Data Abstractions works in real life examples

Example 1

Run
// Demonstration of Data Abstraction using
// Access Specifers, getter and setters
#include <iostream>
using namespace std;

class Rect {
  
  // data members are private and can not be accessed directly
  // access specifiers
  private:
    int len;
    int breadth;
    
    
  public:
  
    // setter for length
    void setLen(int l){
        len = l;
    }
    
    // setter for breadth
    void setBreadth(int b){
        breadth = b;
    }
    
    // getter for length
    int getLen(){
        return len;
    }
    
    // getter for breadth
    int getBreadth(){
        return breadth;
    }
    
    int calculateArea() {
      return len * breadth;
    }

};

int main(){
    
    Rect obj;
    
    // the following will give errors as data members are private now
    // obj.len = 10;
    // obj.breadth = 20;
    
    // Following will be allowed
    // these are called as getters (to get value)
    // and setters (to set value)
    
    obj.setLen(10);
    obj.setBreadth(20);
    
    cout << "Length:" << obj.getLen() << endl;
    cout << "Breadth: " << obj.getBreadth() << endl;
    
    cout << "Area: " << obj.calculateArea();
}

Output

Length:10
Breadth: 20
Area: 200

Example 2

Run
#include <iostream>
using namespace std;

class User {
    
    // data members are private
    private:
    int userID;
    string password;
  
    // member function interface is public
    // to allow specific methods to work with data members
    
    public:
    void createProfile(int id, string pass){
        userID = id;
        password = pass;
        
        cout << "User: " << userID << " account created" << endl;
    }
    
    // using this we don't give interface to share actual password
    // infact the actual password is hidden as private data member
    // we just let the user know if he entered the correct password or not
    // this is data abstraction
    void authenticate(string str){
        
        if(password == str)
            cout << "Login Successful";
        else
            cout << "Incorrect Password";
    }
};

int main(){
    
    User user1;
    
    user1.createProfile(1, "pass123456$");
    
    // following will not work as password is private
    // user1.password = "1234";
    
    // this will work as function in public
    user1.authenticate("pass0000");
    
    return 0;
}

Output

User: 1 account created
Incorrect Password

We have only introduced Access modifiers and Data Abstraction here. We recommend reading about them in detail below –