C++ Encapsulation

Welcome to The Coding College! In this tutorial, we’ll explore Encapsulation in C++, one of the fundamental principles of Object-Oriented Programming (OOP). Encapsulation helps organize code, protect data, and enforce strict boundaries between different parts of a program.

What Is Encapsulation?

Encapsulation is the process of wrapping data (variables) and methods (functions) into a single unit, typically a class. It is achieved by restricting direct access to some of an object’s components and using methods (getters and setters) to access and modify private data.

Key Features of Encapsulation

  1. Data Hiding: Keeps sensitive data safe from unintended access.
  2. Control: Provides control over data by allowing controlled access through methods.
  3. Abstraction: Hides implementation details and exposes only essential functionality.

How Encapsulation Works in C++

Encapsulation is implemented using access specifiers:

  1. private: Data hidden from outside the class.
  2. public: Methods to access or modify private data.

Syntax Example

class ClassName {
private:
    // Private data members (hidden)
public:
    // Public methods to access private members
};

Example: Encapsulation Basics

Here’s an example demonstrating encapsulation in a Student class:

#include <iostream>
using namespace std;

class Student {
private:
    string name;
    int age;

public:
    // Setter for name
    void setName(string n) {
        name = n;
    }

    // Getter for name
    string getName() {
        return name;
    }

    // Setter for age
    void setAge(int a) {
        if (a > 0) {  // Validating age
            age = a;
        } else {
            cout << "Invalid age!" << endl;
        }
    }

    // Getter for age
    int getAge() {
        return age;
    }
};

int main() {
    Student student1;
    student1.setName("Alice");
    student1.setAge(21);

    cout << "Name: " << student1.getName() << endl;
    cout << "Age: " << student1.getAge() << endl;

    return 0;
}

Output:

Name: Alice  
Age: 21  

Why Use Encapsulation?

Benefits of Encapsulation:

  1. Data Security: Prevents direct modification of variables.
  2. Validation: Allows adding validation logic inside setters.
  3. Ease of Maintenance: Isolates data and behavior, making the code easier to manage.
  4. Reusability: Encapsulated code can be reused in different parts of a program.

Real-Life Example: Bank Account

Encapsulation is crucial in real-world scenarios like a bank account system.

#include <iostream>
using namespace std;

class BankAccount {
private:
    string accountHolder;
    double balance;

public:
    // Constructor
    BankAccount(string name, double initialBalance) {
        accountHolder = name;
        if (initialBalance >= 0) {
            balance = initialBalance;
        } else {
            balance = 0;
            cout << "Invalid initial balance! Setting to 0." << endl;
        }
    }

    // Deposit method
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            cout << "Deposited: $" << amount << endl;
        } else {
            cout << "Invalid deposit amount!" << endl;
        }
    }

    // Withdraw method
    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            cout << "Withdrawn: $" << amount << endl;
        } else {
            cout << "Invalid withdrawal amount!" << endl;
        }
    }

    // Display account balance
    void displayBalance() {
        cout << "Account Holder: " << accountHolder << endl;
        cout << "Current Balance: $" << balance << endl;
    }
};

int main() {
    BankAccount account("John Doe", 1000.0);

    account.deposit(500.0);
    account.withdraw(200.0);
    account.displayBalance();

    return 0;
}

Output:

Deposited: $500  
Withdrawn: $200  
Account Holder: John Doe  
Current Balance: $1300  

Encapsulation with Read-Only and Write-Only Variables

Sometimes, you may want variables to be read-only or write-only. This can be achieved by providing only a getter or a setter.

Example:

#include <iostream>
using namespace std;

class Student {
private:
    string name;  // Read-only
    int age;      // Write-only

public:
    // Getter for name (read-only)
    string getName() {
        return name;
    }

    // Setter for age (write-only)
    void setAge(int a) {
        if (a > 0) {
            age = a;
        } else {
            cout << "Invalid age!" << endl;
        }
    }
};

int main() {
    Student student1;
    student1.setAge(20);
    // student1.getAge();  // Error: No getter for age

    cout << "Name: " << student1.getName() << endl;  // Name is read-only

    return 0;
}

Combining Encapsulation and Constructors

Encapsulation becomes even more powerful when combined with constructors for setting initial values.

Example:

#include <iostream>
using namespace std;

class Car {
private:
    string brand;
    int year;

public:
    // Constructor to initialize private members
    Car(string b, int y) {
        brand = b;
        year = y;
    }

    // Getter methods
    string getBrand() {
        return brand;
    }

    int getYear() {
        return year;
    }
};

int main() {
    Car car1("Tesla", 2023);

    cout << "Brand: " << car1.getBrand() << endl;
    cout << "Year: " << car1.getYear() << endl;

    return 0;
}

Output:

Brand: Tesla  
Year: 2023  

Key Points to Remember

  1. Encapsulation combines data and methods into a single unit (class).
  2. Use private to hide sensitive data.
  3. Use public methods (getters and setters) to control access.
  4. Helps improve code readability, maintainability, and security.

Explore More at The Coding College

For more in-depth tutorials, guides, and programming tips, visit The Coding College.

Leave a Comment