1. Encapsulation
  2. Abstraction
  3. Inheritance
  4. Polymorphism

These principles allow user to bundle data, secure it, reuse existing code and process diverse object types through simplified interface.

Encapsulation

it is the process of bundling data and functions into one unit(class) and restrict direct access to some of it component(using access specifiers). it acts as a protective shield for the data.

  • Data is hidden from other classes and accessed only through public methods.
  • Achieved by declaring class variables as private and providing public getter/setter methods.
  • Ensures data integrity and controlled access.

Abstraction

It is the process of hiding implementation detail and only showing the essential details or features to the user. it allow the user to focus on what an object does than how it does. in C++ abstraction is achieved using abstract class and pure function.

Inheritance

It is a mechanism in OOPs languages like C++ where a Class can be derived form another class acquires the properties and behaviours of the base class(form which it derived from). it enables code reusability so that we don’t have to keep writing the same line of code again and again.

  • Enables code reusability by inheriting data members and methods from the base class.
  • Achieved using : followed by an access specifier (public, private, protected).
  • Example: Dog, Cat, Cow can be derived classes of the Animal base class.

Polymorphism

It means having many forms, and it comes from the Greek words poly (many) and morph (forms), this means one entity can take many forms. In C++ polymorphism allows the same method or object to behave differently based on the context.

Compile Time polymorphism

The compiler determines exactly which function or operation to call before the application runs.

Function Overloading You can declare multiple functions with the same name within the same scope, provided they have different parameter counts or types.

Operator Overloading You can redefine how native C++ operators (like +, -, or <<) work when applied to user-defined classes.

Runtime Polymorphism

The specific method to execute is determined while the program runs based on the underlying object type, rather than the type of the pointer or reference. This relies on Inheritance and Virtual Functions.

#include <iostream>
#include <vector>
 
// Base Class
class Animal {
public:
    // Virtual destructor ensures proper cleanup of derived assets
    virtual ~Animal() = default; 
    
    virtual void make_sound()  {
        std::cout << "Generic animal sound!" << std::endl;
    }
};
 
// Derived Class 1
class Dog : public Animal {
public:
    void make_sound() override {
        std::cout << "Woof! Woof!" << std::endl;
    }
};
 
// Derived Class 2
class Cat : public Animal {
public:
    void make_sound() override {
        std::cout << "Meow!" << std::endl;
    }
};
 
int main() {
    // Array of base class pointers storing different derived objects
    std::vector<Animal*> animals;
    animals.push_back(new Dog());
    animals.push_back(new Cat());
 
    // Call behavior dynamically
    for (const auto& animal : animals) {
        animal->make_sound(); // Resolves at runtime to correct implementation
    }
 
    // Clean up memory
    for (auto& animal : animals) {
        delete animal;
    }
}