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.
Person
├── name
├── age
└── address
Student
├── name
├── age
├── address
└── rollNumber
Teacher
├── name
├── age
├── address
└── subjectWithout 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.
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.
class Person
{
public:
void introduce()
{
// Common behavior
}
};
class Student : public Person
{
public:
void study()
{
// Specialized behavior
}
}; Person
Base Class
│
│ inherited by
▼
Student
Derived Class| Term | Meaning |
|---|---|
| Inheritance | Building a class from an existing class |
| Base Class | The class that provides common features |
| Derived Class | The class that inherits and specializes features |
| Inherited Members | Accessible members obtained from the base class |
| Specialization | Adding features specific to the derived class |
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.
class Student
{
public:
std::string name;
int age;
int rollNumber;
};
class Teacher
{
public:
std::string name;
int age;
std::string subject;
};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.
Similarly, a derived class receives accessible features from its base class and can add its own specialized members.
👴 Grandparent
│
│ Common characteristics
▼
👨 Parent
│
│ Inherited + own characteristics
▼
👦 Child
│
└── Inherited + specialized characteristics| Family Analogy | C++ Inheritance |
|---|---|
| Parent | Base class |
| Child | Derived class |
| Shared characteristics | Inherited members |
| Unique traits | Derived class members |
| Family hierarchy | Class hierarchy |
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.
class Person
{
// Base class
};class Student : public Person
{
// Derived class
};| Class | Role | Description |
|---|---|---|
| Person | Base Class | Represents the general concept |
| Student | Derived Class | Represents a specialized Person |
| Teacher | Derived Class | Represents another specialized Person |
Person
Base Class
┌─────┴─────┐
▼ ▼
Student Teacher
Derived DerivedGeneral Syntax
A derived class specifies its base class after a colon in the class declaration.
class BaseClass
{
// Base class members
};
class DerivedClass : accessMode BaseClass
{
// Derived class members
};class Person
{
public:
std::string name;
};
class Student : public Person
{
public:
int rollNumber;
};| Syntax Part | Purpose |
|---|---|
| DerivedClass | Name of the new specialized class |
| : | Introduces the base-class list |
| accessMode | Controls how inherited access is transformed |
| BaseClass | The existing class being inherited |
| Derived class body | Contains specialized members |
class Student : public Person
│ │ │
│ │ └── Base class
│ └───────── Inheritance mode
└──────────────────── Derived classPublic 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.
#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.
student1
┌──────────────────────┐
│ Person Base Part │
│ │
│ name : "Rahul" │
├──────────────────────┤
│ Student Part │
│ │
│ rollNumber : 101 │
└──────────────────────┘Rahul
101A 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.
#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.
Welcome to C++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.
Person
│
▼
StudentTeacher Employee
\ /
\ /
▼ ▼
ProfessorPerson
│
▼
Student
│
▼
GraduateStudent Person
┌────┴────┐
▼ ▼
Student Teacher Person
/ \
▼ ▼
Student Employee
\ /
\ /
▼ ▼
TeachingAssistant| Type | Structure | Example |
|---|---|---|
| Single | One base → one derived | Person → Student |
| Multiple | Multiple bases → one derived | Teacher + Employee → Professor |
| Multilevel | Base → derived → further derived | Person → Student → GraduateStudent |
| Hierarchical | One base → multiple derived | Person → Student and Teacher |
| Hybrid | Combination of structures | Complex class hierarchy |
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 Access | public Inheritance | protected Inheritance | private Inheritance |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | No direct derived access | No direct derived access | No direct derived access |
class Student : public Person
{
// Base public remains public
// Base protected remains protected
};class Student : protected Person
{
// Base public becomes protected
// Base protected remains protected
};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 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.
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 Person
│
▼
Define Student : public Person
│
▼
Create Student student1
│
▼
Student object contains
Person base-class part
│
▼
Access inherited members
│
▼
Access Student members
│
▼
Program EndsWhen 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.
Account
├── SavingsAccount
└── CurrentAccount
Vehicle
├── Car
├── Bike
└── Truck
Character
├── Player
├── Enemy
└── BossInheritance 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.
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
A class declaration without an inheritance mode uses private inheritance by default.
Duplicating members already provided by the base class defeats the purpose of reuse.
The base class is general; the derived class is specialized.
Derived classes cannot directly access private members of the base class.
Code reuse alone does not automatically justify inheritance.
Long inheritance chains can become difficult to understand and maintain.
// ⚠️ Private inheritance by default
class Student : Person
{
};
// ✅ Public inheritance
class Student : public Person
{
};class Person
{
private:
std::string name;
};
class Student : public Person
{
public:
void show()
{
// ❌ Cannot access name directly
// std::cout << name;
}
};class Person
{
private:
std::string name;
public:
const std::string& getName() const
{
return name;
}
};
class Student : public Person
{
public:
void show()
{
std::cout << getName();
}
};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.
class Vehicle
{
};
class Car : public Vehicle
{
};class Engine
{
};
class Car
{
private:
Engine engine;
};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.