Siksha Sarovar

Siksha Sarovar (sikshasarovar.com) is a free educational web application that helps students in India learn programming and prepare for academic and competitive exams. The platform offers structured coding courses (C, C++, Python, Java, HTML, CSS, PHP, Power BI, AI, Machine Learning, Data Science), complete university curriculum notes for BCA/MCA students with previous year question papers, Class 10 and Class 12 CBSE/HBSE school notes, and dedicated preparation material for SSC, UPSC, Banking, Railway and other government exams. Browsing the site is completely free and requires no account. Users may optionally sign in with Google solely to save their learning progress, quiz scores and personal preferences across devices.

Privacy Policy | Terms of Service | Contact Siksha Sarovar | About Siksha Sarovar

v4.0.9 · PWA
Siksha Sarovar logo
Siksha Sarovar
Your Learning Universe

Siksha Sarovar is a free e-learning platform for coding courses, BCA university notes and competitive exam preparation. Optional Google sign-in saves your learning progress across devices.

Initializing knowledge base…
Compiling modules 0%

3.1 Inheritance — Types & Derivation Modes

Lesson 13 of 22 in the free Object Oriented Programming with C++ notes on Siksha Sarovar, written by Rohit Jangra.

3.1 Inheritance — Types & Derivation Modes

What is Inheritance?

Inheritance is the mechanism by which a new class (derived class) acquires the properties and behaviours of an existing class (base class). It enables code reuse, extensibility, and modelling of "is-a" relationships.

class Vehicle {              // base class
public:
    int wheels;
    void start() { cout << "Engine starts\n"; }
};

class Car : public Vehicle {  // derived from Vehicle
public:
    int seats;
    void honk() { cout << "Beep!\n"; }
};

Car c;
c.start();    // inherited from Vehicle
c.wheels = 4; // inherited
c.honk();     // own

Terminology

TermMeaning
Base / Super / Parent classThe class being inherited from
Derived / Sub / Child classThe class doing the inheriting
is-a relationshipCar is a Vehicle
Single inheritanceOne base, one derived
Multiple inheritanceOne derived from multiple bases
Multilevel inheritanceChain: A → B → C
Hierarchical inheritanceOne base, many derived
Hybrid inheritanceMix of above

Syntax

class Derived : access-specifier Base {
    // ...
};

The access-specifier is public, protected, or private — covered shortly.

---

Why Inheritance?

BenefitExplanation
Code reuseDon't rewrite features in every related class
Real-world modelling"is-a" hierarchies match domains naturally
ExtensibilityAdd new specialised types without modifying existing code
Polymorphism foundationVirtual functions need inheritance to work
MaintainabilityFix bug in base → all derived benefit

---

Types of Inheritance

1. Single Inheritance

One base class → one derived class.

   Base
    │
    ▼
   Derived
class A {
public:
    void f1() { cout << "A::f1\n"; }
};

class B : public A {       // single inheritance
public:
    void f2() { cout << "B::f2\n"; }
};

B b;
b.f1();    // from A
b.f2();    // from B

---

2. Multiple Inheritance

A derived class inherits from two or more base classes.

   Base1   Base2
     \     /
      \   /
      Derived
class Worker {
public:
    void work() { cout << "Working\n"; }
};

class Student {
public:
    void study() { cout << "Studying\n"; }
};

class WorkingStudent : public Worker, public Student {  // multiple
public:
    void describe() { cout << "I work and study\n"; }
};

WorkingStudent ws;
ws.work();     // from Worker
ws.study();    // from Student
ws.describe(); // own

Multiple inheritance is powerful but risky — can cause the diamond problem (next lesson).

---

3. Multilevel Inheritance

A chain of inheritance: A → B → C (B derives from A, C derives from B).

   A
    │
    ▼
   B
    │
    ▼
   C
class Grandfather {
public:
    void g_method() { cout << "Grandfather\n"; }
};

class Father : public Grandfather {
public:
    void f_method() { cout << "Father\n"; }
};

class Son : public Father {
public:
    void s_method() { cout << "Son\n"; }
};

Son s;
s.g_method();   // from Grandfather (2 levels up)
s.f_method();   // from Father
s.s_method();   // own

---

4. Hierarchical Inheritance

One base class → multiple derived classes.

        Base
       / | \
      /  |  \
     ▼   ▼   ▼
    D1   D2   D3
class Shape {
public:
    void draw() { cout << "Drawing shape\n"; }
};

class Circle : public Shape { /* ... */ };
class Square : public Shape { /* ... */ };
class Triangle : public Shape { /* ... */ };

Common in real-world OOP — one general type, many specialised subtypes.

---

5. Hybrid Inheritance

A combination of two or more of the above — usually involves multiple + multilevel or multiple + hierarchical.

          Base
         /    \
        ▼      ▼
       D1     D2
         \   /
          ▼ ▼
         D3

This is the classic diamond problem layout — D3 inherits from D1 and D2, both of which inherit from Base. D3 ends up with two copies of Base — ambiguity. Solved with virtual base class (next lesson).

class A {
public:
    int x;
};

class B : public A { /* ... */ };
class C : public A { /* ... */ };

class D : public B, public C {   // diamond — D has two A's
public:
    void test() {
        // x = 5;     // AMBIGUOUS — which A's x?
        B::x = 5;     // explicit qualification
        C::x = 10;
    }
};

---

Comparison of Inheritance Types — quick table

TypeDiagramDescription
SingleA → BOne base, one derived
MultipleA,B → CDerived from two+ bases
MultilevelA → B → CChain
HierarchicalA → B, A → COne base, many derived
HybridmixCombination

---

Derivation Modes — public, protected, private

The access specifier in class Derived : MODE Base determines how base members are inherited:

Visibility transformation

Base memberpublic derivationprotected derivationprivate derivation
publicpublicprotectedprivate
protectedprotectedprotectedprivate
privatenot inheritednot inheritednot inherited
Private base members are never accessible in the derived class, regardless of derivation mode.

Examples

class Base {
public:    int  pub;
protected: int prot;
private:   int priv;
};

class PubDerived : public Base {
    void f() {
        pub  = 1;    // OK — public stays public
        prot = 2;    // OK — protected stays protected
        // priv = 3; // ERROR — private never inherited
    }
};

class ProtDerived : protected Base {
    void f() {
        pub  = 1;    // OK — public becomes protected
        prot = 2;    // OK
        // priv = 3; // ERROR
    }
};

class PrivDerived : private Base {
    void f() {
        pub  = 1;    // OK — public becomes private (still accessible inside class)
        prot = 2;    // OK
        // priv = 3; // ERROR
    }
};

int main() {
    PubDerived d1;
    d1.pub = 5;     // OK — still public outside

    ProtDerived d2;
    // d2.pub = 5;  // ERROR — pub became protected, not accessible from main

    PrivDerived d3;
    // d3.pub = 5;  // ERROR — pub became private
    return 0;
}

What each derivation mode means semantically

ModeSemantic
public"is-a" — Car is a Vehicle; external code can use derived as base
protected"implemented in terms of, internally" — used in further inheritance
private"implemented in terms of, hidden" — composition via inheritance; external code doesn't know
In practice: ~99% of inheritance is public. protected and private derivation are rare in real code.

Default derivation mode

  • For class: private (so class D : Base = class D : private Base)
  • For struct: public

Always be explicit — write public, protected, or private — to avoid confusion.

---

Aggregation vs Composition vs Classification

Classification (Inheritance) — "is-a"

class Car : public Vehicle {};   // Car IS A Vehicle

Composition — "has-a" (strong ownership)

class Engine {};
class Car {
    Engine engine;   // Car HAS A Engine — by value (lifetime tied to Car)
};

Aggregation — "has-a" (weak ownership)

class Department {};
class University {
    vector<Department*> depts;   // University HAS Departments (independent lifetime)
};

When to choose what

RelationshipUse
is-a (Car is a Vehicle)Inheritance
has-a, strong (Car has an Engine — engine destroyed with car)Composition
has-a, weak (University has Departments — but they can exist separately)Aggregation
Modern advice: Prefer composition over inheritance. Inheritance creates tight coupling between base and derived. Composition is more flexible and avoids many OOP design pitfalls.

---

Composition vs Classification — exam comparison

AspectClassification (Inheritance)Composition
Relationship"is-a""has-a"
CouplingTightLoose
FlexibilityLess (compile-time)More (runtime)
Reuse viaInheritingIncluding as member
ReplaceabilityHardEasy
PolymorphismYesYes (via interface composition)

---

Example — Library Management

class Item {
protected:
    int id;
    string title;

public:
    Item(int i, string t) : id(i), title(t) {}
    void display() {
        cout << id << ": " << title << endl;
    }
};

class Book : public Item {       // Book IS A Item
private:
    string author;
public:
    Book(int i, string t, string a) : Item(i, t), author(a) {}
    void showAuthor() {
        cout << "Author: " << author << endl;
    }
};

class Magazine : public Item {   // Magazine IS A Item
private:
    int issue;
public:
    Magazine(int i, string t, int is) : Item(i, t), issue(is) {}
    void showIssue() {
        cout << "Issue: " << issue << endl;
    }
};

int main() {
    Book b(1, "C++ Primer", "Stanley Lippman");
    Magazine m(2, "Time", 47);

    b.display();   // inherited
    b.showAuthor();

    m.display();
    m.showIssue();
    return 0;
}

---

Study deep

  1. Inheritance creates one of the strongest coupling forces in OOP. A derived class depends on the base class's interface AND implementation. Changes to the base ripple to all derived. Use sparingly.
  1. is-a test for choosing inheritance. If "Car is a Vehicle" is naturally true, inherit. If you're saying "Car has-a Vehicle" or "Car uses Vehicle," prefer composition.
  1. Multiple inheritance is controversial. Java forbids it (allows multiple interface inheritance only). C++ allows full multiple inheritance — flexible but enables the diamond problem. Use mixins / interfaces approach for clarity.
  1. The "fragile base class" problem. If many classes inherit from a base, changing the base risks breaking all of them. This is one reason modern systems prefer composition.
  1. Java's "implements" = C++'s pure virtual classes. Java distinguishes "extends" (class inheritance, single) from "implements" (interface inheritance, multiple). C++ doesn't have keywords for this — but a class with only pure virtual methods is effectively an interface.

Key Terms — Lesson 3.1

The terms below define inheritance vocabulary — the third OOP pillar and a guaranteed Unit-III topic.

Inheritance — The OOP mechanism by which a new class (derived / subclass / child) acquires the properties and behaviours of an existing class (base / superclass / parent), with the option to add new members or override inherited ones. Inheritance models the "is-a" relationship and enables code reuse, extensibility, and polymorphism.

Base Class / Parent Class / Superclass — The class being inherited from. Its members are exposed (subject to access specifiers) to the derived class. The base provides the common behaviour that derived classes specialise.

Derived Class / Child Class / Subclass — A class that inherits from another. The derived class can use the base's accessible members, add its own, and override the base's virtual functions.

Single Inheritance — A derived class has one direct base class. The simplest form: class Car : public Vehicle. Easy to understand, no ambiguity issues, the default style in most Java code (where multiple inheritance is forbidden).

Multiple Inheritance — A derived class has two or more direct base classes: class Plane : public Vehicle, public Aircraft. C++ supports it; Java and C# do not (they allow multiple interface inheritance only). Multiple inheritance enables genuine multi-role classes but introduces ambiguity issues (the diamond problem).

Multilevel Inheritance — A chain of inheritance: Vehicle → Car → SportsCar. SportsCar inherits from Car, which inherits from Vehicle. Each level adds specialisation.

Hierarchical Inheritance — One base class has multiple direct derived classesVehicle is inherited by Car, Bike, Truck. The base captures common behaviour; each derived class specialises.

Hybrid Inheritance — A combination of two or more inheritance styles in a single hierarchy — e.g., multiple + multilevel. Hybrid hierarchies often suffer the diamond problem.

Derivation Mode / Access Specifier (in Inheritance) — A specifier (public, protected, or private) used after the colon in the derived class declaration: class Car : public Vehicle. Controls how inherited members appear in the derived class.

Public Derivationclass Derived : public Base. Public members of Base remain public in Derived; protected members remain protected; private members are not accessible. The most common derivation mode; models true "is-a."

Protected Derivationclass Derived : protected Base. Public members of Base become protected in Derived; protected stay protected; private inaccessible. Used rarely — the derived class wants to use the base internally but not expose it.

Private Derivationclass Derived : private Base. Public and protected members of Base become private in Derived. The derived class uses the base implementation but does not expose any inheritance relationship — equivalent to composition in effect. The default if no access specifier is given.

Visibility Inheritance Matrix — The 3×3 table showing how each base-class access level (public/protected/private) maps to derived-class visibility under each derivation mode. Public-derived preserves access; protected-derived caps at protected; private-derived caps at private.

"is-a" Relationship — The semantic test for inheritance. A SportsCar is a Car; Car is a Vehicle; Manager is an Employee. If the relationship is naturally "is-a," inheritance fits. If not, composition is usually the right choice.

"has-a" Relationship — The semantic test for composition. A Car has an Engine; a University has Departments; an Order has Line Items. "has-a" relationships are modelled by including instances of the other class as data members, not by inheriting.

Composition vs Inheritance — Two reuse mechanisms. Inheritance (is-a) makes the derived class a kind of the base; the derived shares the base's interface and implementation. Composition (has-a) embeds another object as a member; the containing class delegates to it but does not inherit its interface. Modern advice: "prefer composition over inheritance" because composition is more flexible.

Aggregation — A form of composition where the contained objects can exist independently of the container. A University aggregates Departments (the Departments could exist without the University). Contrast with strict composition, where contained objects share the container's lifetime (Book composes Chapters).

Override — When a derived class defines a method with the same signature as a base-class method, replacing the base's version. Override is required for runtime polymorphism (combined with virtual). C++11 added the override keyword to make intent explicit and let the compiler catch mismatches.

Hide — When a derived class declares a member (variable or function) with the same name as one in the base class. The derived name hides the base name; accessing the base version requires explicit scope resolution (Base::method()). Hiding is rarely intentional and usually a bug.

Constructor Chaining (in Inheritance) — When a derived object is constructed, the base-class constructor runs first, then the derived constructor. The derived can specify which base constructor via the initialiser list: Derived(int x) : Base(x) {}. Without specification, the base's default constructor is called.

Destructor Chaining (in Inheritance) — When a derived object is destroyed, the derived destructor runs first, then the base destructor. Order is the reverse of construction. For polymorphic base classes, declare the base destructor virtual so derived destructors run correctly through base pointers.

Reusability (in Inheritance) — The economic benefit of inheritance: writing once in the base class, reusing automatically in all derived classes. Reusability is what justifies the cost of inheritance's tight coupling.

Extensibility — The ability to add new derived classes without modifying existing code. New Shape subclasses can be added without touching the rest of the system, as long as they conform to the base Shape interface. The Open-Closed Principle in SOLID.

Fragile Base Class Problem — A maintenance hazard: changing a base class can silently break many derived classes because they depend on the base's behaviour. The more classes inherit from a base, the riskier any change becomes. One of the strongest arguments for shallow hierarchies and composition.

Liskov Substitution Principle (LSP) — Robert Martin's principle (Barbara Liskov, 1987): subtypes must be substitutable for their base types. If Square extends Rectangle but breaks code that relies on Rectangle's behaviour (set-width-independently-of-height), the design violates LSP. Often signals "this should not be inheritance."

Empty Base Optimisation (EBO) — A C++ compiler optimisation: a derived class that inherits from an empty base class (no data members) does not pay the cost of an additional byte for the base subobject. Used heavily by the STL.

---

PYQ pattern (very common): "Explain types of inheritance in C++ with diagrams." — Define inheritance; show 5 types (single, multiple, multilevel, hierarchical, hybrid) with diagrams + 1-line examples each.
PYQ pattern: "Differentiate public, protected and private derivation." — Tabulate the 3×3 visibility transformation; explain semantic of each; mention public is the common case.
PYQ pattern: "What is aggregation? Differentiate it from inheritance / composition." — Define has-a vs is-a; table the differences; show code examples (University with Departments).