OOP: C++ में एनकैप्सुलेशन और पॉलीमॉर्फिज्म: एक विस्तृत मार्गदर्शिका
What is it and why? (real-life analogy)
Imagine you're assembling a robot vacuum cleaner. It has three main parts:
- Motor — it spins the brushes and creates suction.
- Sensors — they see walls and furniture.
- Battery — provides energy.
When you press the "Start" button, you don't think: "Now I'll apply 12 volts to the motor windings, start the PWM controller, and poll the ultrasonic rangefinder." You just say: "Clean the room." Complex magic happens inside the robot, but on the outside — a simple interface.
It's the same in programming. Encapsulation is when we hide complex details inside an object and show only what's needed. Like a TV remote: you press the volume button, you don't go inside with a soldering iron.
Polymorphism is when the same interface works differently depending on the situation. Imagine you have a universal remote. If you point it at the TV — it changes channels. If at the air conditioner — it changes the temperature. The "On" button is the same, but the result is different.
💡 Remember: Encapsulation is about "what's inside is none of your business." Polymorphism is about "one interface — many implementations."
Theory: how it works internally
Encapsulation
In C++, encapsulation is implemented through access modifiers:
private— data is visible only inside the class. No one outside can touch it.protected— data is visible inside the class and its descendants.public— data is visible to everyone.
Best practice: make all fields (variables) private, and access them through public methods (getters and setters).
Polymorphism
Polymorphism comes in two types:
- Static (early binding) — resolved at compile time. This includes function overloading and templates.
- Dynamic (late binding) — resolved during program execution. Used through virtual functions and inheritance.
When you call a method on an object, the compiler checks: "Which exact method should I call?" If the method is virtual — the decision is postponed until program runtime.
⚠️ Important: Without virtual functions, polymorphism doesn't work in C++. If you forget to write virtual, the parent class method will be called, even if you passed a descendant object.
Syntax in C++: all forms and variants
Encapsulation: basic syntax
class RobotVacuum {
private:
int chargeLevel; // Hidden field — no one can change it directly
bool isOn;
public:
// Constructor — create an object
RobotVacuum() {
chargeLevel = 100;
isOn = false;
}
// Getter — get the value
int getCharge() {
return chargeLevel;
}
// Setter — set the value with validation
void setCharge(int newCharge) {
if (newCharge >= 0 && newCharge <= 100) {
chargeLevel = newCharge;
}
}
// Public method — interface
void pressStart() {
if (chargeLevel > 10) {
isOn = true;
cout << "Robot started cleaning!" << endl;
} else {
cout << "Charge me!" << endl;
}
}
};
Polymorphism: virtual functions
class Animal {
public:
// Virtual method — polymorphism
virtual void makeSound() {
cout << "Some animal makes a sound" << endl;
}
};
class Dog : public Animal {
public:
void makeSound() override { // override — checks that the method is indeed virtual
cout << "Woof-woof!" << endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
cout << "Meow!" << endl;
}
};
Access modifiers table
| Modifier | Inside class | In descendant | Outside |
|---|---|---|---|
| private | ✅ Yes | ❌ No | ❌ No |
| protected | ✅ Yes | ✅ Yes | ❌ No |
| public | ✅ Yes | ✅ Yes | ✅ Yes |
Code examples — from simple to complex
Example 1: Simplest encapsulation
#include <iostream>
using namespace std;
class Counter {
private:
int value; // Hidden field
public:
// Constructor
Counter() {
value = 0;
}
// Method to increment
void increment() {
value++;
}
// Method to get the value
int getValue() {
return value;
}
};
int main() {
Counter myCounter;
myCounter.increment();
myCounter.increment();
// myCounter.value = 100; // Error! Field is private
cout << "Value: " << myCounter.getValue() << endl;
return 0;
}
Explanation: We hid the value field and provided only two methods: increment and getValue. No one can set the value directly — only through allowed operations.
Example 2: Setter with validation
class BankAccount {
private:
double balance;
public:
BankAccount() {
balance = 0.0;
}
// Setter with validation
void depositMoney(double amount) {
if (amount > 0) {