Tutorials Logic, IN info@tutorialslogic.com

C++ OOP Basics Classes, Objects, Encapsulation: Notes, Examples & Interview Tips

What is OOP in C++?

Object-oriented programming in C++ organizes code around classes and objects.

A class is a blueprint; an object is a real instance created from that blueprint.

The four core OOP ideas are encapsulation, abstraction, inheritance, and polymorphism.

Object-oriented programming, or OOP, is a programming style where we model real-world or logical entities as objects. Each object can store data and perform actions through functions.

C++ supports procedural programming like C, but it also supports object-oriented programming through classes, objects, constructors, access specifiers, inheritance, virtual functions, and more. OOP helps large programs stay organized because related data and behavior live together.

  • Use OOP when data and behavior naturally belong together.
  • A class defines the structure and behavior.
  • An object is a runtime instance of a class.
  • Methods are functions that belong to a class.
  • Data members are variables that belong to a class.

Class vs Object

Beginners often confuse class and object. The class is only the design. The object is the actual thing created from that design.

Concept Meaning Example
Class Blueprint or template class Student
Object Instance created from a class Student s1;
Data member Variable inside a class name, rollNo, marks
Member function Function inside a class display(), calculateGrade()

Design A Small Class With Clear Ownership

A class combines data with operations that preserve valid state. Start with a BankAccount that owns a balance and exposes deposit and withdraw methods. Keep the balance private so callers cannot assign impossible values directly. Validate constructor arguments and every state-changing operation.

Constructors establish invariants, while destructors release owned resources. Prefer automatic objects and standard library types so RAII handles cleanup. Use const member functions for operations that do not modify observable state, pass large objects by const reference, and initialize members in the constructor initializer list.

Inheritance models an is-a relationship, but composition is often simpler. A Car has an Engine; it is not an Engine. Use virtual functions only when runtime polymorphism is required, add a virtual destructor to polymorphic base classes, and use override so the compiler verifies the intended method relationship.

  • Keep invariant-protecting data private.
  • Establish valid state in constructors.
  • Use RAII and standard library ownership types.
  • Prefer composition for has-a relationships.
  • Use override and virtual destructors for polymorphism.

Four Pillars of OOP

The foundation of OOP is usually explained with four major pillars. These ideas help you design reusable and maintainable programs.

Pillar Meaning C++ Feature
Encapsulation Bind data and methods together and protect internal state class, private, public, getters, setters
Abstraction Show essential behavior and hide implementation details public methods, abstract classes
Inheritance Create a new class from an existing class class Child : public Parent
Polymorphism Same interface, different behavior function overloading, overriding, virtual functions

Access Specifiers in C++

Access specifiers decide where class members can be used. They are central to encapsulation.

Specifier Access Common Use
private Only inside the same class Protect data members
public Accessible from outside the class Expose useful methods
protected Inside class and derived classes Allow controlled inheritance access

Constructor and Destructor

A constructor runs automatically when an object is created. It is commonly used to initialize data members. A destructor runs automatically when an object is destroyed. It is commonly used for cleanup.

  • Constructor name is the same as the class name.
  • Constructor has no return type.
  • Destructor name is the class name with ~ before it.
  • Destructor also has no return type.
  • A class can have multiple constructors using constructor overloading.

Complete C++ OOP Example

This example shows class, object, private data, constructor, member functions, encapsulation, inheritance, and runtime polymorphism in one simple program.

C++ OOP Basics Example

C++ OOP Basics Example
#include <iostream>
#include <string>
using namespace std;

class Account {
private:
    string owner;
    double balance;

public:
    Account(string ownerName, double openingBalance) {
        owner = ownerName;
        balance = openingBalance;
    }

    string getOwner() const {
        return owner;
    }

    double getBalance() const {
        return balance;
    }

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

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

    virtual void printAccountType() const {
        cout << "General account" << endl;
    }

    virtual ~Account() {}
};

class SavingsAccount : public Account {
private:
    double interestRate;

public:
    SavingsAccount(string ownerName, double openingBalance, double rate)
        : Account(ownerName, openingBalance), interestRate(rate) {}

    void printAccountType() const override {
        cout << "Savings account with interest rate "
             << interestRate << "%" << endl;
    }
};

int main() {
    SavingsAccount acc("Asha", 5000, 4.5);

    acc.deposit(1000);
    acc.withdraw(750);

    cout << "Owner: " << acc.getOwner() << endl;
    cout << "Balance: " << acc.getBalance() << endl;

    Account* basePtr = &acc;
    basePtr->printAccountType(); // runtime polymorphism

    return 0;
}

OOP Basics Expected Output

OOP Basics Expected Output
Owner: Asha
Balance: 5250
Savings account with interest rate 4.5%

How the Example Uses OOP

OOP Concept Where It Appears Why It Matters
Class Account and SavingsAccount Groups related data and behavior
Object SavingsAccount acc Creates a usable account instance
Encapsulation owner and balance are private Protects data from direct external modification
Inheritance SavingsAccount inherits Account Reuses common account behavior
Polymorphism virtual printAccountType() Calls derived behavior through base pointer
Abstraction deposit(), withdraw(), getBalance() User calls simple methods without knowing internals

When Should You Use OOP?

OOP is useful when your program has entities with state and behavior. It is not required for every small program, but it becomes powerful as programs grow.

  • Use OOP for models like Student, Employee, Product, Account, Order, Shape, Vehicle, and User.
  • Use OOP when behavior belongs naturally with data.
  • Use OOP when you need reuse through inheritance or composition.
  • Avoid forcing OOP when a simple function is clearer.

OOP Basics vs Classes and Objects

This page gives the big picture of OOP. The Classes and Objects page focuses more deeply on class syntax, object creation, constructors, destructors, getters, setters, and member functions.

  • Start here if you want to understand the OOP model.
  • Go to Classes and Objects when you want more syntax-level practice.
  • Study Inheritance and Polymorphism after this page.
  • Study Encapsulation and Abstraction to improve design clarity.

Rule Of Zero, Value Semantics, And Interface Design

Prefer the Rule of Zero: compose classes from std::string, std::vector, smart pointers, and other RAII types so compiler-generated copy, move, and destruction behavior is correct. When a class directly owns a raw resource, understand the Rule of Five and define or delete copy and move operations deliberately.

Decide whether the type has value semantics, unique identity, or shared ownership. Value types should copy predictably. Unique resources use std::unique_ptr, while shared_ptr should represent genuine shared lifetime rather than convenience. Avoid exposing owning raw pointers and unclear lifetime contracts.

Keep public interfaces small, exception guarantees documented, and dependencies injectable. Avoid deep inheritance trees and fragile base-class assumptions. Test invariants, copying and moving, invalid input, and polymorphic destruction. Performance decisions should follow measurement rather than premature manual memory management.

  • Prefer compiler-generated special members when safe.
  • Define ownership semantics in the type interface.
  • Use unique_ptr as the default dynamic owner.
  • Keep inheritance shallow and substitutable.
  • Test copy, move, destruction, and error guarantees.

Encapsulated value-like class

The methods preserve the balance invariant.

Encapsulated value-like class
class BankAccount {
public:
    explicit BankAccount(double opening) : balance_(opening) {
        if (opening < 0) throw std::invalid_argument(\"negative balance\");
    }

    void deposit(double amount) {
        if (amount <= 0) throw std::invalid_argument(\"invalid deposit\");
        balance_ += amount;
    }

    bool withdraw(double amount) {
        if (amount <= 0 || amount > balance_) return false;
        balance_ -= amount;
        return true;
    }

    double balance() const noexcept { return balance_; }

private:
    double balance_;
};
  • Money normally needs an integer minor-unit or decimal type.
  • The constructor creates a valid object.
  • Callers cannot bypass withdrawal rules.

Polymorphism with RAII ownership

unique_ptr controls lifetime and the base destructor is virtual.

Polymorphism with RAII ownership
class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;
};

class Circle final : public Shape {
public:
    explicit Circle(double radius) : radius_(radius) {}
    double area() const override {
        return 3.141592653589793 * radius_ * radius_;
    }
private:
    double radius_;
};

std::unique_ptr<Shape> shape = std::make_unique<Circle>(2.0);
  • override catches signature mistakes.
  • The virtual destructor enables safe base-pointer deletion.
  • Prefer stack values when dynamic polymorphism is unnecessary.
Before you move on

C++ OOP Basics Classes, Objects, Encapsulation: Notes, Examples & Interview Tips Mastery Check

1 checks
  • Why private data members are used.

OOP Ownership Boundary

  • Unclear resource ownership

    If a class owns a resource, define copy and move behavior or use an RAII type that already does. Raw owning pointers make double deletion and leaks likely.

C++ OOP Basics Questions Learners Ask

C++ supports object-oriented programming, but it is multi-paradigm. You can write procedural, object-oriented, generic, and functional-style C++.

A class is a blueprint. An object is an actual instance created from that blueprint.

Private data members prevent outside code from putting an object into an invalid state. Public methods can validate changes.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.