OOP in C++

Learn the ideas behind C++ OOP

Understand Advanced Programming Concepts in C++

C++ is powerful because it combines low-level control with high-level abstractions. This page explains the most important modern C++ ideas in a clear and visual way: object-oriented programming, templates, STL, Modern cpp.

Object-Oriented Programming

OOP organizes code around objects, which combine data and behavior. Instead of writing everything as disconnected functions, you model real concepts: a Car, a BankAccount, a Student, or a FileManager.

Why use OOP?

  • Better code organization
  • Reusable logic
  • Easier maintenance
  • Real-world modeling

Core pillars

  • Encapsulation
  • Abstraction
  • Inheritance
  • Polymorphism

Encapsulation

Encapsulation means hiding internal details and exposing only what the user of a class needs. A class protects its state and controls how that state is changed. This reduces bugs and keeps your program predictable.

Example idea: a bank account should not let outside code directly set the balance to anything. Instead, it should offer controlled operations like deposit() and withdraw().

Encapsulation Example in C++

bank_account.cpp
#include <iostream>
#include <string>

class BankAccount {
private:
    // keeping this private
    std::string owner;
    double balance;

public:
    BankAccount(const std::string& name, double initialBalance)
        : owner(name), balance(initialBalance) {}

    void deposit(double amount) {
        if (amount > 0) balance += amount;
    }

    bool withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
            return true;
        }
        return false;
    }

    void show() const {
        std::cout << "Owner: " << owner
                  << ", Balance: " << balance << '\n';
    }
};

int main() {
    BankAccount acc("Alice", 1000);
    acc.deposit(500);
    acc.withdraw(200);
    acc.show();
}

Inheritance

Inheritance allows one class to reuse and extend another. A derived class inherits common members from a base class, which helps reduce duplicated code.

Base class: defines shared behavior
Derived class: adds specialized behavior

Polymorphism

Polymorphism means one interface can represent many forms. With virtual functions, you can call the same method name on different objects, and each object responds in its own way.

This is essential for flexible, extensible systems like graphics engines, game entities, plugin systems, and UI frameworks.

Inheritance + Polymorphism Example

shapes.cpp
#include <iostream>
#include <memory>
#include <vector>

class Shape {
public:
    virtual void draw() const {
        std::cout << "Drawing a generic shape\n";
    }

    virtual ~Shape() = default;
};

class Circle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing a circle\n";
    }
};

class Rectangle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing a rectangle\n";
    }
};

int main() {
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Circle>());
    shapes.push_back(std::make_unique<Rectangle>());

    for (const auto& shape : shapes) {
        shape->draw();
    }
}

Templates

Templates allow you to write generic and reusable code in C++. Instead of writing separate functions or classes for different data types, you can define a single template that works with many types.

Templates are the foundation of the Standard Template Library (STL), enabling powerful containers like vector, map, and array.

Generic Programming

With templates, algorithms can work with any compatible data type while maintaining type safety and performance. The compiler generates the correct implementation automatically during compilation.

Templates help eliminate code duplication while keeping programs flexible and efficient.

Template Function Example

template_swap.cpp
#include <iostream>

template <typename T>
void swapValues(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 10, y = 20;
    swapValues(x, y);
    std::cout << "x: " << x << ", y: " << y << '\n';

    double a = 1.5, b = 3.7;
    swapValues(a, b);
    std::cout << "a: " << a << ", b: " << b << '\n';
}

Operator Overloading

Operator overloading allows you to define how operators such as +, -, *, ==, and others behave when applied to user-defined types like classes and structs. This lets your custom objects behave more naturally and readably, similar to built-in types.

With operator overloading, objects like vectors, matrices, or complex numbers can use expressions such as a + b instead of verbose function calls.

Why It Matters

Properly overloaded operators make C++ code cleaner and more intuitive. Instead of calling methods like add(), developers can write expressions that look like standard arithmetic operations.

Many C++ libraries rely on operator overloading to create expressive APIs, especially in mathematics, graphics, and scientific computing.

Operator Overloading Example

vector_add.cpp
#include <iostream>

class Vector {
public:
    int x, y;

    Vector(int x, int y) : x(x), y(y) {}

    Vector operator+(const Vector& other) const {
        return Vector(x + other.x, y + other.y);
    }
};

int main() {
    Vector a(2, 3);
    Vector b(4, 5);

    Vector result = a + b;

    std::cout << "Result: (" << result.x << ", " << result.y << ")" << '\n';
}

The Standard Template Library (STL)

The Standard Template Library (STL) is one of the core strengths of modern C++. It provides reusable, efficient, and well-tested tools for handling data and performing common operations. Because STL is built with templates, its components work with any data type you choose.

Containers

Containers are classes designed to store collections of elements. Each container has its own strengths:

• vector — fast dynamic array
• list — doubly‑linked list
• deque — fast insert/remove at both ends
• set — automatically sorted, no duplicates
• map — key‑value pairs, sorted by key
• queue / stack — FIFO / LIFO structures

Choosing the right container makes your code faster and simpler.

Algorithms

Algorithms are pre‑built functions that perform common tasks on container data. They work with any container through iterators. Examples include:

• sort — sort elements
• find — search for a value
• count — count matches
• reverse — reverse a range
• max_element / min_element

Algorithms help you write less code while keeping it fast and safe.

Iterators

Iterators act like smart pointers that move through container elements. Algorithms use iterators instead of depending on container types.

Common iterator operations:
• it++ — move forward
• *it — access element
• begin() / end() — define a range

This makes STL algorithms flexible and interchangeable between containers.

STL Example (Containers + Algorithms + Iterators)

stl_example.cpp
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector nums = {5, 1, 9, 3, 7};

    // Sort the vector using an STL algorithm
    std::sort(nums.begin(), nums.end());

    // Print using iterators
    for (auto it = nums.begin(); it != nums.end(); ++it) {
        std::cout << *it << " ";
    }
}

What makes C++ “modern”?