Elective Object Oriented Programming in C++

Object Oriented Programming in C++Unit 58 min read

Inheritance in C++: Types, Code Reuse & Problem-Solving

Unit 5 of Object Oriented Programming in C++ covers inheritance (how classes inherit properties/methods), its five types (single, multilevel, hierarchical, multiple, hybrid), the diamond problem, and real-world applications in banking, e-commerce, and system design—with code examples, visual traces, and exam-focused ti

TAKEAWAYS:

  • Inheritance lets a derived class reuse code from a base class via : syntax, saving time and reducing errors.
  • Five types of inheritance (single, multilevel, hierarchical, multiple, hybrid) solve different design needs—each has pros/cons.
  • The diamond problem (ambiguous base class) is fixed using virtual inheritance in C++.
  • Real-world systems (e.g., Khalti’s payment hierarchy, Ncell’s billing structure) use inheritance to organize complex logic.
  • Exam focus: Code traces, UML diagrams, and explaining why a design choice (e.g., virtual keyword) matters.

1. What is Inheritance?

Inheritance is an OOP mechanism where a derived class (child) inherits properties and behaviors from a base class (parent). It promotes code reusability and logical hierarchy.

Key Terms

  • Base Class: The class being inherited from (e.g., Person).
  • Derived Class: The class that inherits (e.g., Employee).
  • public/protected/private inheritance: Controls access to base class members.
  • : syntax: Used to declare inheritance (e.g., class Employee : public Person).

Why Use Inheritance?

  • Avoid redundancy: Write once, reuse everywhere.
  • Model real-world relationships: E.g., an Employee is-a Person.
  • Extensibility: Add new features without modifying existing code.

2. Syntax and Example

#include <iostream>
using namespace std;

class Person {          // Base class
public:
    string name;
    int age;
    void display() {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
};

class Employee : public Person {  // Derived class
public:
    int employee_id;
    void showDetails() {
        display();  // Reuses base class method
        cout << "ID: " << employee_id << endl;
    }
};

int main() {
    Employee emp;
    emp.name = "Ramesh";
    emp.age = 30;
    emp.employee_id = 101;
    emp.showDetails();
    return 0;
}

Output:

Name: Ramesh, Age: 30
ID: 101

Visual Trace: Memory Layout

classDiagram
    class Person {
        -string name
        -int age
        +display()
    }
    class Employee {
        -int employee_id
        +showDetails()
    }
    Person <|-- Employee : Inherits from

3. Types of Inheritance

Type Definition Example Pros Cons
Single One base → one derived class. class Car : public Vehicle Simple, easy to debug. Limited flexibility.
Multilevel Chain of inheritance (A→B→C). Person → Employee → Manager Logical hierarchy (e.g., org charts). Deep inheritance can be complex.
Hierarchical One base → multiple derived classes. Vehicle → Car, Bike, Truck Models shared traits (e.g., transport). Base class changes affect all.
Multiple One derived class inherits from two bases. class AndroidPhone : public Phone, public MediaPlayer Combines features (e.g., phone + music). Diamond problem risk.
Hybrid Mix of multiple types (e.g., single + multiple). Vehicle → Car → ElectricCar (also inherits from Battery). Flexible for complex systems. Hard to maintain.

4. The Diamond Problem & Solution

Problem: When a derived class inherits from two classes that both inherit from the same base, ambiguity arises.

classDiagram
    class A {
        +show()
    }
    class B {
        +show()
    }
    class C {
        +show()
    }
    class D {
        +show()
    }
    A <|-- B
    A <|-- C
    B <|-- D
    C <|-- D
    D --> A : Ambiguous!

Solution: Virtual Inheritance

class A {
public:
    int x;
};
class B : virtual public A {};  // Virtual inheritance
class C : virtual public A {};
class D : public B, public C {};

int main() {
    D obj;
    obj.x = 10;  // No ambiguity!
    cout << obj.x;
    return 0;
}

Key Point: Use virtual in the first inheritance to ensure a single copy of the base class.


5. Real-World Applications

Example 1: Khalti’s Payment System

  • Base Class: PaymentMethod (fields: amount, transactionId).
  • Derived Classes:
    • CreditCardPayment (adds cardNumber, expiryDate).
    • BankTransfer (adds accountNumber).
  • Why? Reuses common logic (e.g., calculateFee()) while extending for specific methods.

Example 2: Ncell’s Billing

  • Base Class: Customer (fields: name, phoneNumber).
  • Derived Classes:
    • PrepaidCustomer (adds balance, topUp()).
    • PostpaidCustomer (adds billingCycle, generateBill()).
  • Why? Avoids duplicating Customer data for each plan type.

Example 3: Daraz’s Order Processing

  • Base Class: Order (fields: orderId, customerId, status).
  • Derived Classes:
    • FoodOrder (adds deliveryTime, restaurantId).
    • ElectronicsOrder (adds warrantyPeriod).
  • Why? Shared methods like updateStatus() are inherited, reducing code.

6. Worked Example: Bank Loan System

Scenario: A bank offers Loan (base) with types HomeLoan and CarLoan (derived). Both need calculateInterest() but have different rates.

#include <iostream>
using namespace std;

class Loan {
protected:
    double principal;
    int years;
public:
    Loan(double p, int y) : principal(p), years(y) {}
    virtual double calculateInterest() = 0;  // Pure virtual → abstract class
};

class HomeLoan : public Loan {
public:
    HomeLoan(double p, int y) : Loan(p, y) {}
    double calculateInterest() override {
        return (principal * 0.08 * years);  // 8% rate
    }
};

class CarLoan : public Loan {
public:
    CarLoan(double p, int y) : Loan(p, y) {}
    double calculateInterest() override {
        return (principal * 0.12 * years);  // 12% rate
    }
};

int main() {
    HomeLoan hl(500000, 5);
    CarLoan cl(200000, 3);
    cout << "Home Loan Interest: " << hl.calculateInterest() << endl;
    cout << "Car Loan Interest: " << cl.calculateInterest() << endl;
    return 0;
}

Output:

Home Loan Interest: 200000
Car Loan Interest: 72000

Visual Trace: Object Creation

classDiagram
    class Loan {
        -principal
        -years
        +calculateInterest()
    }
    class HomeLoan {
        +calculateInterest()
    }
    class CarLoan {
        +calculateInterest()
    }
    Loan <|-- HomeLoan : Overrides
    Loan <|-- CarLoan : Overrides

7. Advantages and Disadvantages

Advantages Disadvantages
Code Reusability: Reduces duplication. Complexity: Deep inheritance is hard to debug.
Extensibility: Easy to add features. Tight Coupling: Changes in base class affect all derived classes.
Logical Modeling: Mirrors real-world hierarchies. Performance Overhead: Virtual functions add slight runtime cost.
Polymorphism: Enables runtime method binding. Diamond Problem: Requires careful design.

8. Exam Tip

  1. Code Traces: Always show the state after each step (e.g., constructor calls in multilevel inheritance).
  2. UML Diagrams: Draw inheritance hierarchies for questions on types (e.g., "Design a system for a university with Person → Student → Undergrad").
  3. Diamond Problem: Expect questions on virtual inheritance—explain why it’s needed.
  4. Real-World Links: Connect examples to banks (loans), e-commerce (orders), or telecom (billing).
  5. Key Terms: Define abstract classes, pure virtual functions, and access specifiers (public/private inheritance).

Practice Question: Design a class hierarchy for a library system with Member (base) and StudentMember/FacultyMember (derived). Include a method borrowBook() overridden in each derived class. Draw the UML diagram and write the C++ code.

Based on the PU BE Computer (PU) syllabus for Object Oriented Programming in C++, unit 5.

Discussion

Loading…