CSC166 Object Oriented Programming

Object Oriented ProgrammingUnit 58 min read

Inheritance & Polymorphism: Types, Chains, Ambiguity & Access Specifiers

Unit 5 of Object Oriented Programming covers inheritance hierarchies (single/multiple/multilevel/hybrid), polymorphism (compile-time vs. run-time), constructor/destructor chains, access specifiers (public/private/protected), and ambiguity resolution in C++. Real-world examples include eSewa's transaction hierarchy, Dar

TAKEAWAYS:

  • Inheritance enables code reuse via is-a relationships (e.g., EmployeeSalary is-a Employee) with public, private, or protected access rules.
  • Polymorphism lets one interface work for multiple types: compile-time (operator overloading) vs. run-time (virtual functions).
  • Constructor/destructor chains execute in base-to-derived order; ambiguity in multiple inheritance is resolved via virtual base classes.
  • Protected members balance encapsulation and inheritance; private inheritance hides implementation but breaks is-a semantics.
  • Real-world systems (e.g., Ncell’s Customer→PrepaidCustomer hierarchy) use these to model hierarchical data efficiently.

1. Inheritance: The "Is-A" Relationship

Inheritance allows a derived class to inherit properties/methods from a base class. It promotes code reuse and hierarchical classification.

Types of Inheritance

classDiagram
    class Base {
        +method()
    }
    class Derived1 {
        +method()
    }
    class Derived2 {
        +method()
    }
    class Hybrid {
        +method()
    }
    Base <|-- Derived1 : Single
    Base <|-- Derived2 : Single
    Derived1 <|-- Hybrid : Multilevel
    Base <|-- Hybrid : Multiple
    note for Hybrid "Hybrid = Multilevel + Multiple"
    note for Base "Base Class"
    note for Derived1 "Single Inheritance"
    note for Derived2 "Single Inheritance"
    note for Hybrid "Hybrid Inheritance"
  • Single Inheritance: One base → one derived (e.g., Vehicle → Car).
  • Multilevel Inheritance: Chain of single inheritances (e.g., Animal → Mammal → Dog).
  • Multiple Inheritance: One derived from multiple bases (e.g., Student inherits from Person and Employee).
  • Hierarchical Inheritance: Multiple derived from one base (e.g., Shape → Circle, Rectangle).
  • Hybrid Inheritance: Mix of multiple and multilevel (e.g., Vehicle → Car and Truck → ElectricCar).

Real-World Example: eSewa’s Transaction System

classDiagram
    class Transaction {
        +amount
        +process()
    }
    class ElectricityBill {
        +units
        +calculateFee()
    }
    class MobileRecharge {
        +network
        +validateNetwork()
    }
    Transaction <|-- ElectricityBill
    Transaction <|-- MobileRecharge
  • Why? ElectricityBill and MobileRecharge are-a Transaction, sharing common fields (e.g., amount) but overriding process() for custom logic.

2. Access Specifiers in Inheritance

Controls visibility of base class members in derived classes.

Specifier Base Class Access Derived Class Access Example Use Case
Public Public/Protected/Private Public/Protected Vehicle → Car (exposes speed)
Protected Public/Protected Protected Employee → Manager (hides salary)
Private Public/Protected Private Database → User (hides all)

Key Rule:

  • Public inheritance = is-a (e.g., Dog is-a Animal).
  • Private inheritance = implemented-in-terms-of (e.g., Smartphone uses-a Battery).

Example: Ncell’s Billing System

class Customer {
protected:
    string name;
    int id;
public:
    void display() { cout << name; }
};

class PrepaidCustomer : private Customer { // Hides Customer's interface
    double balance;
public:
    void recharge(double amount) { balance += amount; }
};
  • Why? PrepaidCustomer uses Customer’s data but hides it (e.g., Ncell’s internal billing logic).

3. Constructor and Destructor Chains

Order of Execution:

  1. Base class constructor → Derived class constructor → Member objects.
  2. Destructors reverse: Derived → Base.

Example: Daraz Order Processing

class Order {
public:
    Order() { cout << "Order created\n"; }
    ~Order() { cout << "Order closed\n"; }
};

class FoodOrder : public Order {
    string item;
public:
    FoodOrder(string i) : item(i) { cout << "Food: " << item << "\n"; }
    ~FoodOrder() { cout << "Food order cancelled\n"; }
};

Trace:

Order created          // Base constructor
Food: Pizza           // Derived constructor
[Order processed...]
Food order cancelled  // Derived destructor
Order closed          // Base destructor

Real-World Tie-In:

  • When you place a Daraz order, the system first initializes the base Order (ID, date), then the derived FoodOrder (item details). If cancelled, destructors reverse the process.

4. Polymorphism: One Interface, Many Forms

Polymorphism enables one interface to work for multiple types.

Types

Type Mechanism Example Code Example
Compile-Time Operator Overloading + for int and string cout << obj1 + obj2;
Run-Time Virtual Functions Base class pointer to derived Base* ptr = new Derived();

Example: NEPSE Stock Prices

class Stock {
public:
    virtual void display() { cout << "Base stock\n"; }
};

class NEPSEStock : public Stock {
public:
    void display() override { cout << "NEPSE: " << price << "\n"; }
    double price;
};

Trace:

Stock* ptr = new NEPSEStock();
ptr->display(); // Output: "NEPSE: 1200.50" (run-time binding)

Why Virtual?

  • Without virtual, ptr->display() would call Stock::display() (compile-time binding).

5. Ambiguity in Multiple Inheritance

Problem: Derived class inherits same method from two bases. Solution: Use virtual base classes or scope resolution (::).

Example: Kathmandu Traffic Routes

classDiagram
    class Vehicle {
        +route()
    }
    class Electric {
        +route()
    }
    class HybridCar {
        +route()
        +route()
    }
    Vehicle <|-- HybridCar : Inherits
    Electric <|-- HybridCar : Inherits
    note for HybridCar.route "Ambiguity: Which route()?"
    note for Vehicle.route "Vehicle::route()"
    note for Electric.route "Electric::route()"
    note for HybridCar "Solution: Use scope resolution (e.g., Vehicle::route())"

Ambiguity:

HybridCar car;
car.route(); // Error: Which `route()`?

Fix 1: Virtual Base Class

class Vehicle {
public:
    virtual void route() { cout << "Road\n"; }
};
class Electric : virtual public Vehicle { // Virtual base
    void route() override { cout << "Electric path\n"; }
};

Fix 2: Scope Resolution

car.Vehicle::route(); // Calls Vehicle::route()

6. Advantages and Disadvantages of Inheritance

Advantages Disadvantages
Code reuse (DRY principle) Complex hierarchies → hard to maintain
Extensibility (add features easily) Tight coupling between classes
Logical hierarchy (e.g., Animal→Dog) Ambiguity in multiple inheritance
Polymorphism (flexible interfaces) Overuse → "fragile base class" problem

Real-World Trade-Off:

  • eSewa uses inheritance for transaction types but avoids deep hierarchies to simplify updates.

Exam Tip

  1. Diagrams > Text: Always draw inheritance trees (e.g., Base → Derived1 → Derived2) and state transitions (e.g., constructor/destructor chains).
  2. Code + Trace: For polymorphism questions, always show:
    • Base/derived class definitions.
    • A virtual function example.
    • A trace table of constructor/destructor calls.
  3. Ambiguity Fixes: Know both virtual base classes and scope resolution (::).
  4. Access Specifiers: Memorize the public/private/protected rules for derived classes.
  5. Real-World Links: Connect examples to Ncell billing, Daraz orders, or eSewa transactions to score extra marks.

Visual Summary:

Based on the TU BSc CSIT syllabus for Object Oriented Programming (CSC166), unit 5.

Discussion

Loading…