Practical Examples of Encapsulation in C++
Encapsulation is one of the fundamental principles of object-oriented programming (OOP). It involves bundling data (variables) and methods (functions) that operate on the data into a single unit, typically a class. Encapsulation also restricts direct access to some of the object's components, promoting data hiding and ensuring controlled access through public methods.
Why Use Encapsulation?
Encapsulation offers several benefits, including:
- Protecting data from unauthorized access or modification.
- Improving code maintainability by isolating changes.
- Enabling modular design by encapsulating functionality within classes.
- Allowing validation or preprocessing of data before modification.
Practical Example 1: Bank Account Management
This example demonstrates encapsulation by controlling access to a bank account's balance:
#include <iostream>
class BankAccount {
private:
double balance;
public:
BankAccount() : balance(0) {}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
} else {
std::cout << "Invalid deposit amount.\n";
}
}
void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
} else {
std::cout << "Invalid withdrawal amount.\n";
}
}
double getBalance() const {
return balance;
}
};
int main() {
BankAccount account;
account.deposit(1000);
std::cout << "Balance: " << account.getBalance() << std::endl;
account.withdraw(500);
std::cout << "Balance: " << account.getBalance() << std::endl;
account.withdraw(600); // Invalid withdrawal
return 0;
}
Output:
Balance: 1000
Balance: 500
Invalid withdrawal amount.
The private balance member is protected from direct access, ensuring controlled modifications through the deposit and withdraw methods.
Practical Example 2: Student Management System
In a student management system, encapsulation can ensure that data like grades and names are accessed and modified in a controlled way:
#include <iostream>
class Student {
private:
std::string name;
int grade;
public:
void setName(const std::string& studentName) {
name = studentName;
}
void setGrade(int studentGrade) {
if (studentGrade >= 0 && studentGrade <= 100) {
grade = studentGrade;
} else {
std::cout << "Invalid grade.\n";
}
}
std::string getName() const {
return name;
}
int getGrade() const {
return grade;
}
};
int main() {
Student student;
student.setName("Alice");
student.setGrade(85);
std::cout << "Name: " << student.getName() << ", Grade: " << student.getGrade() << std::endl;
student.setGrade(150); // Invalid grade
return 0;
}
Output:
Name: Alice, Grade: 85
Invalid grade.
Encapsulation ensures that the grade is validated before being set, preventing incorrect or out-of-range values.
Practical Example 3: Car Class
This example demonstrates encapsulation for a car object, managing its speed:
#include <iostream>
class Car {
private:
int speed;
public:
Car() : speed(0) {}
void accelerate(int amount) {
if (amount > 0) {
speed += amount;
std::cout << "Accelerated to " << speed << " km/h\n";
}
}
void brake(int amount) {
if (amount > 0 && speed - amount >= 0) {
speed -= amount;
std::cout << "Slowed down to " << speed << " km/h\n";
} else {
std::cout << "Invalid brake operation.\n";
}
}
int getSpeed() const {
return speed;
}
};
int main() {
Car myCar;
myCar.accelerate(50);
myCar.brake(20);
myCar.brake(40); // Invalid operation
return 0;
}
Output:
Accelerated to 50 km/h
Slowed down to 30 km/h
Invalid brake operation.
Encapsulation ensures that the speed is modified only through methods that enforce logical rules.
Conclusion
Encapsulation is a critical principle in C++ that helps build robust and maintainable programs. By grouping data and methods together and restricting direct access to private members, developers can ensure data integrity, enforce validation, and maintain modularity.