LearnContact
Lesson 2310 min read

Inheritance

Without inheritance, common data members and functions would need to be rewritten in multiple related classes. In this lesson, you will learn how C++ inheritance allows derived classes to reuse and extend the properties and behaviors of existing base classes.

Introduction

In the previous lesson, you learned how encapsulation protects object state and provides controlled access through a public interface.

Now imagine that you need to create several related classes. A Person may have a name, age, and address. A Student is also a person but additionally has a roll number. A Teacher is also a person but additionally has a subject.

Related Classes
Person
├── name
├── age
└── address

Student
├── name
├── age
├── address
└── rollNumber

Teacher
├── name
├── age
├── address
└── subject

Without inheritance, the common Person members would need to be repeated in both Student and Teacher. This creates duplicate code and makes maintenance more difficult.

Repeated Classes

  • Student repeats person data.
  • Teacher repeats person data.
  • Common changes must be made multiple times.
  • Duplicate code increases maintenance work.

Shared Base Class

  • Person stores common features.
  • Student reuses Person.
  • Teacher reuses Person.
  • Specialized classes add only their unique features.
Create Common Person Class
Student Inherits Person
Teacher Inherits Person
Add Specialized Features
The Main Idea

Inheritance allows related classes to reuse common features from an existing class while adding their own specialized behavior.

What is Inheritance?

Inheritance is an object-oriented programming feature that allows one class to acquire accessible data members and member functions from another class.

The existing class that provides common features is called the base class. The new class that builds upon it is called the derived class.

Basic Inheritance
class Person
{
public:
    void introduce()
    {
        // Common behavior
    }
};

class Student : public Person
{
public:
    void study()
    {
        // Specialized behavior
    }
};
Inheritance Relationship
        Person
      Base Class
          │
          │ inherited by
          ▼
        Student
     Derived Class
TermMeaning
InheritanceBuilding a class from an existing class
Base ClassThe class that provides common features
Derived ClassThe class that inherits and specializes features
Inherited MembersAccessible members obtained from the base class
SpecializationAdding features specific to the derived class
Simple Definition

Inheritance allows a new class to reuse and extend an existing class.

Why Do We Need Inheritance?

Many software systems contain related types that share common state or behavior. Rewriting those common features in every class creates duplication.

Without Inheritance

  • Common code is repeated.
  • Classes become unnecessarily large.
  • Changes must be repeated.
  • Related types are not clearly organized.
  • Maintenance becomes more difficult.

With Inheritance

  • Common code can be reused.
  • Duplication is reduced.
  • Shared behavior is centralized.
  • Related classes form clear hierarchies.
  • Specialized classes can extend existing behavior.
Without Inheritance
class Student
{
public:
    std::string name;
    int age;
    int rollNumber;
};

class Teacher
{
public:
    std::string name;
    int age;
    std::string subject;
};
With Inheritance
class Person
{
public:
    std::string name;
    int age;
};

class Student : public Person
{
public:
    int rollNumber;
};

class Teacher : public Person
{
public:
    std::string subject;
};

Reusability

Common features can be written once and reused.

Less Duplication

Repeated members and functions can be centralized.

Maintainability

Shared behavior can often be updated in one place.

Hierarchy

Related types can be organized from general to specialized.

Extensibility

New specialized classes can build upon existing classes.

Clear Modeling

Inheritance can represent genuine is-a relationships.

Real-World Analogy

Consider a family relationship. A child may inherit certain characteristics from a parent while also having unique characteristics of their own.

Grandparent
Parent
Child

Similarly, a derived class receives accessible features from its base class and can add its own specialized members.

Family Analogy
👴 Grandparent
      │
      │ Common characteristics
      ▼
👨 Parent
      │
      │ Inherited + own characteristics
      ▼
👦 Child
      │
      └── Inherited + specialized characteristics
Family AnalogyC++ Inheritance
ParentBase class
ChildDerived class
Shared characteristicsInherited members
Unique traitsDerived class members
Family hierarchyClass hierarchy
Analogy Limitation

C++ inheritance is a programming relationship between types. It does not behave exactly like biological inheritance, so class design should be based on logical type relationships rather than the analogy alone.

Important Terminology

Base Class

The existing class that provides common state or behavior.

Derived Class

The new class that inherits from and specializes the base class.

Inheritance Relationship

The connection between a derived class and its base class.

Inherited Members

Accessible members available through the base-class part of the derived object.

Specialization

Features added specifically for the derived type.

Class Hierarchy

An organization of related base and derived classes.

Base Class
class Person
{
    // Base class
};
Derived Class
class Student : public Person
{
    // Derived class
};
ClassRoleDescription
PersonBase ClassRepresents the general concept
StudentDerived ClassRepresents a specialized Person
TeacherDerived ClassRepresents another specialized Person
Class Hierarchy
             Person
            Base Class
          ┌─────┴─────┐
          ▼           ▼
       Student      Teacher
       Derived      Derived

General Syntax

A derived class specifies its base class after a colon in the class declaration.

General Syntax
class BaseClass
{
    // Base class members
};

class DerivedClass : accessMode BaseClass
{
    // Derived class members
};
Example
class Person
{
public:
    std::string name;
};

class Student : public Person
{
public:
    int rollNumber;
};
Syntax PartPurpose
DerivedClassName of the new specialized class
:Introduces the base-class list
accessModeControls how inherited access is transformed
BaseClassThe existing class being inherited
Derived class bodyContains specialized members
Syntax Breakdown
class Student : public Person
      │          │      │
      │          │      └── Base class
      │          └───────── Inheritance mode
      └──────────────────── Derived class
Public Inheritance

Public inheritance is the most common form when the derived class represents a true specialized version of the base class.

Example 1: Basic Inheritance

In this example, Student publicly inherits from Person. The Student object contains a Person base-class part and its own Student-specific member.

Example 1
#include <iostream>
#include <string>

class Person
{
public:
    std::string name;
};

class Student : public Person
{
public:
    int rollNumber;
};

int main()
{
    Student student1;

    student1.name = "Rahul";
    student1.rollNumber = 101;

    std::cout << student1.name
              << std::endl;

    std::cout << student1.rollNumber;

    return 0;
}

How the Program Works

  • Person defines the public name member.
  • Student publicly inherits from Person.
  • Student adds its own rollNumber member.
  • student1 is created as a Student object.
  • student1.name accesses the inherited public member.
  • student1.rollNumber accesses the Student-specific member.
  • Both values are displayed.
Conceptual Object Representation
student1
┌──────────────────────┐
│ Person Base Part     │
│                      │
│ name : "Rahul"       │
├──────────────────────┤
│ Student Part         │
│                      │
│ rollNumber : 101     │
└──────────────────────┘
Create Student Object
Set Inherited name
Set Own rollNumber
Display name
Display rollNumber
Output
Rahul
101
Derived Object

A derived object includes a base-class subobject together with the members added by the derived class.

Example 2: Inheriting Member Functions

Inheritance can make accessible base-class member functions available through derived objects as well.

Example 2
#include <iostream>

class Person
{
public:
    void display()
    {
        std::cout << "Welcome to C++";
    }
};

class Student : public Person
{
};

int main()
{
    Student student1;

    student1.display();

    return 0;
}

How the Program Works

  • Person defines the public display() function.
  • Student publicly inherits from Person.
  • Student does not define its own display() function.
  • student1 is created as a Student object.
  • student1.display() finds the inherited Person function.
  • The inherited function executes.
Create Student Object
Call display()
Find Inherited Function
Execute Person::display()
Display Message
Output
Welcome to C++
Inheritance Includes Behavior

A derived class can reuse accessible member functions from its base class, not only data members.

Types of Inheritance

C++ class relationships can form several common inheritance structures. These are usually described as single, multiple, multilevel, hierarchical, and hybrid inheritance.

1️⃣ Single Inheritance

One derived class inherits from one base class.

2️⃣ Multiple Inheritance

One derived class inherits from more than one direct base class.

3️⃣ Multilevel Inheritance

A derived class becomes a base class for another class.

4️⃣ Hierarchical Inheritance

Multiple derived classes inherit from the same base class.

5️⃣ Hybrid Inheritance

A hierarchy combines multiple inheritance structures.

Single Inheritance
Person
   │
   ▼
Student
Multiple Inheritance
Teacher      Employee
    \          /
     \        /
      ▼      ▼
      Professor
Multilevel Inheritance
Person
   │
   ▼
Student
   │
   ▼
GraduateStudent
Hierarchical Inheritance
         Person
       ┌────┴────┐
       ▼         ▼
    Student    Teacher
Hybrid Inheritance
        Person
       /      \
      ▼        ▼
  Student    Employee
      \        /
       \      /
        ▼    ▼
   TeachingAssistant
TypeStructureExample
SingleOne base → one derivedPerson → Student
MultipleMultiple bases → one derivedTeacher + Employee → Professor
MultilevelBase → derived → further derivedPerson → Student → GraduateStudent
HierarchicalOne base → multiple derivedPerson → Student and Teacher
HybridCombination of structuresComplex class hierarchy
Complex Hierarchies Need Care

Multiple and hybrid inheritance can introduce ambiguity and the diamond problem. These advanced cases require careful design and may involve virtual inheritance.

Access Modes in Inheritance

The inheritance mode determines how public and protected members of the base class are exposed through the derived class.

Base Member Accesspublic Inheritanceprotected Inheritanceprivate Inheritance
publicpublicprotectedprivate
protectedprotectedprotectedprivate
privateNo direct derived accessNo direct derived accessNo direct derived access
Public Inheritance
class Student : public Person
{
    // Base public remains public
    // Base protected remains protected
};
Protected Inheritance
class Student : protected Person
{
    // Base public becomes protected
    // Base protected remains protected
};
Private Inheritance
class Student : private Person
{
    // Base public becomes private
    // Base protected becomes private
};

Public Inheritance

  • Models an is-a relationship.
  • Base public interface remains public.
  • Most common for type hierarchies.
  • Supports substitutability when designed correctly.

Non-Public Inheritance

  • Changes inherited accessibility.
  • Does not normally represent a public is-a relationship.
  • Used less frequently.
  • Composition is often clearer for reuse-only relationships.
Private Members Still Exist

Private base-class members are part of the base-class subobject, but the derived class cannot access them directly. They remain accessible through suitable base-class member functions.

Default Inheritance Mode

When class is used, omitted inheritance access defaults to private. When struct is used, omitted inheritance access defaults to public.

Program Execution Flow

The program first defines the general base class, then defines a specialized derived class, and finally creates and uses an object of the derived type.

Program Starts
Define Base Class
Define Derived Class
Create Derived Object
Use Inherited Members
Use Own Members
Program Ends
Detailed Execution
Program Starts
      │
      ▼
Define Person
      │
      ▼
Define Student : public Person
      │
      ▼
Create Student student1
      │
      ▼
Student object contains
Person base-class part
      │
      ▼
Access inherited members
      │
      ▼
Access Student members
      │
      ▼
Program Ends
Construction Order

When a derived object is created, its base-class subobject is initialized before the derived-class part. Destruction occurs in the reverse order.

Real-World Applications

Inheritance is useful when a system contains genuine specialized forms of a more general type.

Banking

Account can provide common behavior for SavingsAccount and CurrentAccount.

Vehicle Management

Vehicle can provide common features for Car, Bike, and Truck.

Employee Management

Employee can provide common features for Manager, Developer, and Tester.

Hospital Systems

Person can be specialized into Doctor, Patient, and Nurse.

Game Development

Character can provide common behavior for Player, Enemy, and Boss.

User Interfaces

A common Widget type can be specialized into Button, TextBox, and Menu components.

Example Hierarchies
Account
├── SavingsAccount
└── CurrentAccount

Vehicle
├── Car
├── Bike
└── Truck

Character
├── Player
├── Enemy
└── Boss
Use Genuine Relationships

Inheritance works best when each derived type is genuinely a specialized form of its base type.

Advantages of Inheritance

Code Reuse

Common behavior can be shared by related classes.

Reduced Duplication

Repeated members can be centralized in a base class.

Extensibility

Derived classes can add specialized features.

Hierarchical Design

Related types can be organized logically.

Maintainability

Shared implementation can often be updated centrally.

Polymorphism

Public inheritance can support runtime polymorphism through virtual functions.

  • Reuses common data and behavior.
  • Reduces unnecessary code duplication.
  • Supports specialization of existing types.
  • Creates organized class hierarchies.
  • Can make related classes easier to extend.
  • Centralizes shared functionality.
  • Provides a foundation for polymorphism.
  • Can model genuine is-a relationships.
Inheritance Also Creates Coupling

A derived class depends on its base-class design. Changes to the base class can affect derived classes, so inheritance should be used deliberately rather than only to avoid writing code.

Common Beginner Mistakes

Forgetting public Inheritance

A class declaration without an inheritance mode uses private inheritance by default.

Rewriting Existing Members

Duplicating members already provided by the base class defeats the purpose of reuse.

Confusing Base and Derived Classes

The base class is general; the derived class is specialized.

Accessing Private Base Members Directly

Derived classes cannot directly access private members of the base class.

Using Inheritance for Every Reuse Case

Code reuse alone does not automatically justify inheritance.

Creating Deep Hierarchies

Long inheritance chains can become difficult to understand and maintain.

Forgetting the Inheritance Mode
// ⚠️ Private inheritance by default
class Student : Person
{
};

// ✅ Public inheritance
class Student : public Person
{
};
Accessing Private Base Data
class Person
{
private:
    std::string name;
};

class Student : public Person
{
public:
    void show()
    {
        // ❌ Cannot access name directly
        // std::cout << name;
    }
};
Use the Base Interface
class Person
{
private:
    std::string name;

public:
    const std::string& getName() const
    {
        return name;
    }
};

class Student : public Person
{
public:
    void show()
    {
        std::cout << getName();
    }
};
Private Members Are Not Directly Accessible

The base-class private state still belongs to the base-class part of the derived object, but derived-class code must use the accessible interface provided by the base class.

Best Practices

  • Use public inheritance only when the derived class represents a genuine is-a relationship.
  • Keep base classes focused on truly common responsibilities.
  • Keep derived classes specialized.
  • Prefer composition for has-a relationships.
  • Avoid using inheritance only for implementation reuse.
  • Keep inheritance hierarchies shallow when possible.
  • Protect base-class implementation details.
  • Use constructors to establish valid base and derived state.
  • Design public base classes carefully because derived classes depend on them.
  • Use virtual destructors when a polymorphic base class may be deleted through a base pointer.
  • Avoid unnecessary multiple inheritance.
  • Prefer clear relationships over complex hierarchies.

Is-A Relationship

  • Student is a Person.
  • Car is a Vehicle.
  • SavingsAccount is an Account.
  • Button is a Widget.

Has-A Relationship

  • Car has an Engine.
  • House has a Room.
  • Computer has a Processor.
  • Order has Products.
Inheritance for Is-A
class Vehicle
{
};

class Car : public Vehicle
{
};
Composition for Has-A
class Engine
{
};

class Car
{
private:
    Engine engine;
};
Ask the Relationship Question

If you can naturally say “Derived is a Base,” inheritance may be appropriate. If the relationship is “Object has a Component,” composition is usually more suitable.

Frequently Asked Questions

What is inheritance?

Inheritance is a C++ feature that allows a derived class to build upon an existing base class.

What is a base class?

A base class is the class that provides common features to one or more derived classes.

What is a derived class?

A derived class is a class that inherits from a base class and can add specialized members.

What does public inheritance mean?

Public inheritance preserves the public and protected accessibility of accessible base members and normally represents an is-a relationship.

What are the five common types of inheritance?

They are single, multiple, multilevel, hierarchical, and hybrid inheritance.

Can a derived class access private members of its base class directly?

No. It must use accessible base-class member functions or other permitted mechanisms.

Do private base members disappear from the derived object?

No. The base-class subobject still contains its private state, but derived-class code cannot access that state directly.

What is the default inheritance mode for a class?

Private inheritance.

What is the default inheritance mode for a struct?

Public inheritance.

When should inheritance be used?

Inheritance should be used when the derived type genuinely represents a specialized form of the base type.

What is the difference between inheritance and composition?

Inheritance commonly represents an is-a relationship, while composition represents a has-a relationship.

Why can deep inheritance hierarchies be problematic?

They increase coupling and make behavior, construction, dependencies, and changes more difficult to understand.

Key Takeaways

  • Inheritance allows a class to build upon another class.
  • The existing general class is called the base class.
  • The specialized class is called the derived class.
  • Derived objects contain a base-class subobject.
  • Accessible data members and functions can be reused.
  • C++ supports single, multiple, multilevel, hierarchical, and hybrid inheritance structures.
  • Public inheritance is the most common mode for is-a relationships.
  • Public, protected, and private inheritance transform accessibility differently.
  • Derived classes cannot directly access private base-class members.
  • Private base state still exists inside the base-class subobject.
  • Inheritance reduces duplication when common behavior genuinely belongs in a shared base class.
  • Inheritance should model logical relationships, not merely code reuse.
  • Composition is usually better for has-a relationships.
  • Deep and complex hierarchies should be avoided when simpler designs are possible.
  • Inheritance provides an important foundation for polymorphism.

Summary

Inheritance is a fundamental object-oriented feature that allows a derived class to build upon an existing base class.

The base class contains common state or behavior, while derived classes represent more specialized types that can reuse accessible base features and add their own members.

C++ supports several inheritance structures, including single, multiple, multilevel, hierarchical, and hybrid inheritance. It also provides public, protected, and private inheritance modes that control how base-class accessibility is transformed.

Inheritance is most effective when it represents a genuine is-a relationship. For has-a relationships and implementation reuse without a type relationship, composition is often the clearer design.

By understanding base classes, derived classes, inherited members, access modes, and class hierarchies, you are now prepared for polymorphism, where related objects can respond differently through a common interface.

Next Lesson →

Polymorphism