C++ OOP Basics Object-Oriented Programming
Four Pillars

C++ Object-Oriented Programming: Complete Guide

Master C++ OOP fundamentals: classes, objects, inheritance, polymorphism, encapsulation, and abstraction with real-world examples and best practices.

Encapsulation

Data hiding and protection

Inheritance

Code reusability and hierarchy

Polymorphism

Many forms, single interface

Abstraction

Hide complexity, show essentials

C++ Tutorial · OOP Concepts

Object-oriented programming models real-world entities with classes. Learn encapsulation, constructors, destructors, and how the this pointer ties methods to instances.

C++ classes and objects infographic: class blueprint vs object instance, access specifiers public private protected, Student example program, memory allocation, and member functions
C++ classes & objects visual guide — class as blueprint, object as instance, access specifiers, example program with setData and display, per-object memory layout, and encapsulation for OOP interview prep.

What you will learn

  • Define classes with public/private members
  • Create objects and call member functions
  • Write constructors and destructors
  • Use this for chaining and self-reference
  • Apply encapsulation to hide implementation

Why this topic matters

OOP is central to C++ frameworks (Qt, game engines, enterprise). Interview loops always include class design questions.

Key terms & indexing

C++ OOP C++ classes constructors destructors C++ encapsulation C++

Introduction to Object-Oriented Programming

Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around data, or objects, rather than functions and logic. C++ is a multi-paradigm language that fully supports OOP.

Real-World Analogy

Think of a Car as a class. Each individual car (Toyota Camry, Honda Civic) is an object. All cars inherit basic properties from the Vehicle class. Different cars (electric, gasoline) implement the same interface (start(), stop()) differently - that's polymorphism!

Why Use OOP?
  • Modularity for easier maintenance
  • Code reusability through inheritance
  • Data hiding and security
  • Flexibility through polymorphism
  • Better problem-solving approach
  • Easier collaboration in teams
OOP vs Procedural Programming
  • Procedural: Focus on functions
  • OOP: Focus on data and objects
  • Procedural: Data is global or passed
  • OOP: Data is encapsulated in objects
  • Procedural: Harder to maintain
  • OOP: Easier to scale and maintain

C++ OOP Concepts Overview

The following table explains the fundamental concepts of Object-Oriented Programming in C++:

Concept Definition C++ Implementation Real-World Example
Class Blueprint or template for creating objects class ClassName { }; Car design blueprint
Object Instance of a class with actual data ClassName obj; Actual car on the road
Encapsulation Bundling data and methods together, hiding implementation private: and public: Capsule containing medicine
Inheritance Deriving new classes from existing ones class Child : public Parent Child inherits traits from parents
Polymorphism One interface, multiple implementations virtual functions, overriding Person can be Student, Teacher, etc.
Abstraction Hiding complex reality while exposing essentials Abstract classes, interfaces Car dashboard (hides engine complexity)
Constructor Special method called when object is created ClassName() { } Car assembly process
Destructor Special method called when object is destroyed ~ClassName() { } Car recycling process

1. Classes and Objects: The Foundation

A class is a user-defined data type that holds both data (attributes) and functions (methods). An object is an instance of a class.

Class Definition Syntax
class ClassName {
private:
    // Private members (accessible only within class)
    dataType privateVariable;
    
protected:
    // Protected members (accessible within class and derived classes)
    dataType protectedVariable;
    
public:
    // Public members (accessible from anywhere)
    dataType publicVariable;
    
    // Constructor
    ClassName(parameters) {
        // Initialization code
    }
    
    // Member functions (methods)
    returnType methodName(parameters) {
        // Method implementation
    }
    
    // Destructor
    ~ClassName() {
        // Cleanup code
    }
};

Class and Object Examples

1. class definition
class Account {
  int id; double bal;
public:
  void deposit(double a);
};
2. object create
Account acc;
acc.deposit(100);
3. member access
cout << acc.getBalance();
4. this pointer
void setId(int id){ this->id=id; }
5. static count
static int count;
Account::count++;
6. scope resolution
void Account::deposit(double a){ bal+=a; }
Class Design Best Practices:
  • Use meaningful, descriptive class names
  • Keep data members private (encapsulation)
  • Provide public getter/setter methods if needed
  • Initialize all data members in constructors
  • Follow the Rule of Three/Five for resource management
  • Make member functions const when they don't modify object
Common Mistakes:
  • Forgetting semicolon after class definition
  • Making all data members public (breaks encapsulation)
  • Not initializing pointers in constructors
  • Memory leaks (not deleting dynamic memory)
  • Shallow copying when deep copy is needed
  • Not making destructor virtual in base class
BankAccount
- accountNumber: string
- accountHolder: string
- balance: double
+ BankAccount()
+ BankAccount(string, string, double)
+ ~BankAccount()
+ getAccountNumber(): string
+ getAccountHolder(): string
+ getBalance(): double
+ setAccountHolder(string): void
+ deposit(double): void
+ withdraw(double): bool
+ displayAccountInfo(): void

2. Constructors and Destructors

Constructors initialize objects when they are created. Destructors clean up when objects are destroyed. C++ provides several types of constructors.

Default Constructor
  • No parameters
  • Called when: ClassName obj;
  • Initializes with default values
  • Compiler provides if no constructors defined
Parameterized Constructor
  • Accepts parameters
  • Called when: ClassName obj(params);
  • Initializes with provided values
  • Allows custom initialization
Copy Constructor
  • Creates copy of existing object
  • Called when: ClassName obj2 = obj1;
  • Deep vs shallow copy
  • Compiler provides default if not defined

Constructor Examples

1. Default ctor
Student() { name=""; }
2. Param ctor
Student(string n): name(n) {}
3. Copy ctor
Student(const Student& o): name(o.name) {}
4. Initializer list
Point(int x,int y): x(x),y(y) {}
5. Destructor
~Student() { cout<<"bye"; }
6. = delete copy
Student(const Student&)=delete;
Constructor Best Practices:
  • Use initializer lists for member initialization (more efficient)
  • Provide a default constructor if objects might be created without arguments
  • Make copy constructor do deep copy when class has pointer members
  • Follow the Rule of Three: If you need destructor, copy constructor, or copy assignment, you likely need all three
  • Use delegating constructors (C++11) to avoid code duplication
  • Initialize all data members in every constructor

3. Encapsulation: Data Hiding and Protection

Encapsulation is the bundling of data and methods that operate on that data within a single unit (class), and restricting direct access to some of the object's components.

Access Specifiers
class Example {
private:    // Accessible ONLY within this class
    int secretData;
    
protected:  // Accessible within this class AND derived classes
    int familyData;
    
public:     // Accessible from ANYWHERE
    int publicData;
    
    // Getter method (accessor)
    int getSecretData() const {
        return secretData;
    }
    
    // Setter method (mutator) with validation
    void setSecretData(int value) {
        if (value >= 0) {
            secretData = value;
        }
    }
};

Encapsulation Examples

1. private fields
private:
  string name;
  int marks;
2. public getters
string getName() const { return name; }
3. setter validation
void setMarks(int m){ if(m>=0) marks=m; }
4. friend function
friend ostream& operator<<(ostream& os, const Student& s);
5. const method
int getMarks() const { return marks; }
6. hide implementation
// users call deposit(), not bal+=

Encapsulation Benefits

  • Data Hiding: Internal representation is hidden from outside
  • Increased Security: Controlled access through public methods
  • Flexibility & Maintainability: Can change internal implementation without affecting code that uses the class
  • Data Validation: Setters can validate data before storing
  • Modularity: Classes can be developed and tested independently

4. Inheritance: Code Reusability and Hierarchy

Inheritance allows a new class (derived class) to inherit properties and behaviors from an existing class (base class). This promotes code reusability and establishes relationships between classes.

Inheritance Syntax
// BASE CLASS (Parent)
class BaseClass {
protected:
    int protectedData;
public:
    void baseMethod() { }
};

// DERIVED CLASS (Child) - Single Inheritance
class DerivedClass : public BaseClass {
public:
    void derivedMethod() {
        protectedData = 10; // Can access protected members
        baseMethod();       // Can access public methods
    }
};

// MULTIPLE INHERITANCE
class MultiDerived : public Base1, public Base2 {
    // Inherits from both Base1 and Base2
};

Inheritance Examples

1. base class
class Vehicle { protected: int speed; };
2. public inherit
class Car : public Vehicle { };
3. override method
void start() override { speed=10; }
4. base ctor call
Car(): Vehicle() {}
5. upcast pointer
Vehicle* v = new Car();
6. virtual dtor
virtual ~Vehicle()=default;
Types of Inheritance
  • Single: One base, one derived
  • Multiple: Multiple base classes
  • Multilevel: Chain of inheritance
  • Hierarchical: Multiple derived from one base
  • Hybrid: Combination of above
Access Specifiers in Inheritance
  • public: Most common, "is-a" relationship
  • protected: Less common, intermediate access
  • private: Rare, "implemented-in-terms-of"
  • Affects how base members are inherited
Important Rules
  • Always make destructor virtual in base class
  • Use public inheritance for "is-a" relationships
  • Avoid multiple inheritance when possible
  • Use virtual inheritance to solve diamond problem
  • Initialize all base classes in constructor

5. Polymorphism: One Interface, Multiple Forms

Polymorphism allows objects of different classes to be treated as objects of a common base class. It enables one interface to be used for a general class of actions.

Polymorphism Implementation
// BASE CLASS with virtual function
class Base {
public:
    virtual void show() {        // Virtual function
        cout << "Base show()" << endl;
    }
    
    virtual void display() = 0;  // Pure virtual function (abstract)
    
    virtual ~Base() {}           // Virtual destructor
};

// DERIVED CLASS overriding virtual function
class Derived : public Base {
public:
    void show() override {       // Override keyword (C++11)
        cout << "Derived show()" << endl;
    }
    
    void display() override {
        cout << "Derived display()" << endl;
    }
};

Polymorphism Examples

1. virtual function
virtual double pay() const = 0;
2. override pay
double pay() const override { return base+bonus; }
3. base pointer call
Employee* e = new Manager();
cout<<e->pay();
4. vtable idea
// runtime picks Manager::pay
5. pure virtual
class Shape { virtual double area()=0; };
6. dynamic_cast
Manager* m = dynamic_cast<Manager*>(e);

Types of Polymorphism in C++

Compile-Time Polymorphism (Static)
  • Function Overloading: Same name, different parameters
  • Operator Overloading: Custom behavior for operators
  • Templates: Generic programming
  • Resolved at compile time
  • Faster execution
Runtime Polymorphism (Dynamic)
  • Virtual Functions: Function overriding
  • Function Overriding: Derived class redefines base function
  • Achieved through inheritance
  • Resolved at runtime
  • Flexible but slightly slower
Virtual Function Rules:
  • Always declare destructor as virtual in base class
  • Use override keyword (C++11) to explicitly indicate overriding
  • Use final keyword (C++11) to prevent further overriding
  • Pure virtual functions make a class abstract (cannot instantiate)
  • Virtual functions have small performance overhead (vtable lookup)
  • Constructors cannot be virtual, destructors should be virtual

6. Abstraction: Hiding Complexity

Abstraction is the process of hiding complex implementation details and showing only essential features to the user. In C++, abstraction is achieved through abstract classes and interfaces.

Abstraction Implementation
// ABSTRACT CLASS (contains pure virtual function)
class AbstractClass {
public:
    // Pure virtual function - makes class abstract
    virtual void essentialOperation() = 0;
    
    // Virtual destructor
    virtual ~AbstractClass() {}
    
    // Can have implemented methods too
    void commonOperation() {
        cout << "Common implementation" << endl;
    }
};

// CONCRETE CLASS implementing abstraction
class ConcreteClass : public AbstractClass {
public:
    void essentialOperation() override {
        cout << "Concrete implementation" << endl;
    }
};

Abstraction Examples

1. abstract class
class Device { public: virtual void on()=0; };
2. interface usage
void use(Device& d){ d.on(); }
3. hide details
class Printer : public Device { /* ... */ };
4. public API only
printer.print(doc); // not driver bytes
5. impl in .cpp
// header declares, cpp defines
6. dependency invert
App depends on Device*, not Printer
Abstraction Implementation
  • Abstract classes (pure virtual functions)
  • Interfaces (all pure virtual functions)
  • Header files (.h) as abstraction
  • Libraries and APIs
  • Design Patterns (Factory, Strategy, etc.)
Abstraction vs Encapsulation
  • Abstraction: Design level, what to show
  • Encapsulation: Implementation level, how to hide
  • Abstraction solves design problems
  • Encapsulation solves implementation problems
  • Both work together for good OOP design
When to Use Abstraction
  • Creating libraries/frameworks
  • Defining contracts/interfaces
  • Hiding platform-specific code
  • Creating plug-in architectures
  • When implementation may change

7. OOP Best Practices and Design Principles

OOP Design Principles (SOLID)
  • S - Single Responsibility: One class, one reason to change
  • O - Open/Closed: Open for extension, closed for modification
  • L - Liskov Substitution: Derived classes should substitute base classes
  • I - Interface Segregation: Many specific interfaces better than one general
  • D - Dependency Inversion: Depend on abstractions, not concretions
Common OOP Mistakes
  • God classes (too many responsibilities)
  • Deep inheritance hierarchies
  • Not making destructor virtual in base class
  • Using public data members
  • Circular dependencies between classes
  • Overusing inheritance when composition is better
  • Not following Rule of Three/Five

OOP Design Examples

1. GOOD: SRP
class Invoice { void total(); };
2. BAD: god class
class App { void ui(); void db(); };
3. GOOD: compose
class Car { Engine engine; };
4. BAD: deep tree
class X: public Y: public Z {}
5. GOOD: interface
class Logger { virtual void log(string)=0; };
6. GOOD: const-correct
int getX() const { return x; }

Golden Rules of C++ OOP

Design Principles
  • Encapsulate what varies
  • Program to interfaces
  • Favor composition
  • Keep it simple
C++ Specific
  • Virtual destructor in base class
  • Rule of Three/Five/Zero
  • Const correctness
  • RAII (Resource Acquisition Is Initialization)
Modern C++ (C++11+)
  • Use override and final
  • Prefer smart pointers
  • Use move semantics
  • Use auto for type deduction

Frequently asked questions

What is the difference between class and struct?

Default access: struct members are public, class members private—otherwise nearly identical in C++.

When is the destructor called?

When an object’s lifetime ends—scope exit or delete—for stack and heap objects respectively.

What is the Rule of Three/Five?

If you manage resources, define/copy/move/destructor appropriately—expanded in advanced OOP topics.