BIT153 Object Oriented Programming

Object Oriented ProgrammingUnit 410 min read

Inheritance: Hierarchies, Access Control & Method Overriding

Unit 4 of Object Oriented Programming: Explores how classes reuse and extend code via inheritance hierarchies, access modifiers, constructor/destructor chaining, and method overriding—with real-world parallels in apps like Daraz (order inheritance) and NTC (network device classes).

TAKEAWAYS

  • Inheritance lets a derived class reuse and extend a base class’s attributes/methods (e.g., Vehicle → Car).
  • Access specifiers (public, private, protected) control inheritance visibility (e.g., protected allows subclass access but hides from external code).
  • Constructor/destructor chaining ensures proper initialization: base class constructors run first, then derived classes (reverse for destructors).
  • Method overriding enables runtime polymorphism by letting derived classes redefine virtual base-class methods.
  • Virtual base classes break diamond inheritance ambiguity (e.g., Animal → Dog and Cat inheriting from Animal).
  • Multilevel/hiarchical inheritance models real-world taxonomies (e.g., Employee → Manager → CEO).

1. Definitions & Core Concepts

1.1 What is Inheritance?

Inheritance is an IS-A relationship where a derived class (subclass) inherits properties and behaviors from a base class (superclass). It promotes code reuse and hierarchical classification.

classDiagram
    class Vehicle {
        +int wheels
        +void start()
    }
    class Car {
        +int seats
        +void start() // Overrides Vehicle::start()
    }
    Vehicle <|-- Car

Example in Real Life:

  • Daraz’s Order System A ProductOrder class inherits from Order, reusing fields like orderId and customer while adding productDetails. This avoids rewriting common logic for every order type.

1.2 Types of Inheritance

Type Description Example
Single One base, one derived class. Animal → Dog
Multilevel Chain of inheritance (A→B→C). Vehicle → Car → ElectricCar
Hierarchical One base, multiple derived classes. Shape → Circle & Rectangle
Multiple Not supported in C++ (but possible in Java/C#). —
Hybrid Combination of above (e.g., multilevel + hierarchical). —

Visualization:

classDiagram
    class Shape {
        +double area()
    }
    class Circle {
        +double radius
        +double area()
    }
    class Rectangle {
        +double length
        +double width
        +double area()
    }
    Shape <|-- Circle
    Shape <|-- Rectangle
    class MultilevelExample {
        +void exampleMethod()
    }
    Circle <|-- MultilevelExample

2. Access Specifiers in Inheritance

Access modifiers restrict how derived classes access base class members:

Modifier Base Class Access Derived Class Access External Code Access
public Allowed Allowed Allowed
protected Allowed Allowed Blocked
private Allowed Blocked Blocked

Example:

class Base {
public:  int pub = 1;
protected: int pro = 2;
private:  int pri = 3;
};
class Derived : public Base {
public:
    void show() {
        cout << pub << ", " << pro << ", " << pri; // Error: 'pri' is private
    }
};

Fix: Use protected for pri if derived classes need access.


3. Constructor & Destructor Chaining

3.1 Constructor Order

Constructors execute top-down (base → derived). Destructors execute bottom-up (derived → base).

Example:

class Base { public: Base() { cout << "Base constructor\n"; } };
class Derived : public Base {
public: Derived() { cout << "Derived constructor\n"; }
};
int main() {
    Derived d; // Output:
    // Base constructor
    // Derived constructor
}

Visual Trace:

Step 1: Base() called → "Base constructor"
Step 2: Derived() called → "Derived constructor"

3.2 Explicit Base Constructor Call

If the base class has parameters, explicitly call its constructor:

class Base { public: Base(int x) { cout << x; } };
class Derived : public Base {
public: Derived() : Base(10) {} // Calls Base(int)
};

4. Method Overriding & Virtual Functions

VehicleCarTruckElectricCarManualCar
Inheritance hierarchy showing method overriding: `start()` is overridden in `Car` and `ElectricCar`.

4.1 Overriding Base Methods

A derived class can redefine a virtual base-class method to provide specific behavior.

Example:

class Animal {
public:
    virtual void speak() { cout << "Animal sound\n"; }
};
class Dog : public Animal {
public:
    void speak() override { cout << "Bark!\n"; } // Overrides
};
int main() {
    Animal* a = new Dog();
    a->speak(); // Output: "Bark!" (runtime polymorphism)
}

Key Points:

  • Use virtual in the base class.
  • Use override in the derived class (C++11+).
  • Dynamic binding ensures the correct method is called at runtime.

4.2 final Keyword

  • class Base final: Prevents inheritance.
  • void speak() final: Prevents overriding in derived classes.

5. Virtual Base Classes (Diamond Problem)

Problem: Ambiguity when a class inherits from two classes that share a common base.

classDiagram
    class Animal {
        +void eat()
    }
    class Mammal {
        +void nurse()
    }
    class Dog {
        +void bark()
    }
    class Cat {
        +void meow()
    }
    Mammal <|-- Dog
    Mammal <|-- Cat
    Animal <|-- Mammal

Solution: Declare the common base (Animal) as virtual in the intermediate class (Mammal):

class Mammal : virtual public Animal { ... };

6. Advantages & Disadvantages

Advantages Disadvantages
Code reuse (avoids duplication). Tight coupling (hard to modify base class).
Extensibility (easy to add features). Complexity (deep hierarchies are hard to debug).
Polymorphism (runtime flexibility). Diamond problem (requires virtual base classes).
022.54567.590Code Reuse90Extensibility85Maintainability80Complexity70Tight Coupling65Relative Benefit/Drawback (%)
Balanced pros and cons of inheritance in OOP.

7. Real-World Applications

In the Real World

  1. NTC’s Network Devices

    • Idea: Inheritance models devices like Router, Switch, and Modem, all inheriting from NetworkDevice.
    • How: Common methods (e.g., connect(), disconnect()) are defined in NetworkDevice, while derived classes add device-specific logic (e.g., Switch::forwardPacket()).
  2. Pathao’s Ride Classification

    • Idea: Vehicle (base) → Car, Bike, Van (derived). Each inherits startEngine() but overrides calculateFare().
    • Example: A Bike ride’s fare calculation differs from a Car ride’s.
  3. NEPSE’s Stock Market Hierarchy

    • Idea: Investment (base) → Stock, Bond, MutualFund (derived). Each inherits purchase() but overrides calculateReturn().

8. Worked Example: Bank Account Hierarchy

Scenario: A bank has SavingsAccount and CurrentAccount, both inheriting from BankAccount.

#include <iostream>
using namespace std;

class BankAccount {
protected:
    string accountHolder;
    double balance;
public:
    BankAccount(string name, double amt) : accountHolder(name), balance(amt) {}
    virtual void display() {
        cout << "Account Holder: " << accountHolder << ", Balance: " << balance << endl;
    }
    virtual void withdraw(double amt) {
        if (balance >= amt) balance -= amt;
        else cout << "Insufficient funds!\n";
    }
};

class SavingsAccount : public BankAccount {
private:
    double interestRate;
public:
    SavingsAccount(string name, double amt, double rate)
        : BankAccount(name, amt), interestRate(rate) {}
    void addInterest() {
        balance += balance * interestRate / 100;
    }
    void display() override {
        cout << "Savings Account: " << accountHolder << ", Balance: " << balance
             << ", Interest Rate: " << interestRate << "%\n";
    }
};

int main() {
    SavingsAccount s("Alice", 1000, 5.0);
    s.withdraw(200);
    s.addInterest();
    s.display();
    // Output:
    // Savings Account: Alice, Balance: 805, Interest Rate: 5%
}

Trace Table:

Step Action balance interestRate Output
1 SavingsAccount("Alice", 1000, 5.0) 1000 5.0 —
2 s.withdraw(200) 800 5.0 —
3 s.addInterest() 840 5.0 —
4 s.display() 840 5.0 "Savings Account: Alice, ..."

9. Exam Tip

  • Focus on:
    • Constructor/destructor chaining (order matters!).
    • Access specifiers (public, protected, private in inheritance).
    • Virtual functions and override keyword.
    • Diamond problem and virtual base classes.
  • Common Pitfalls:
    • Forgetting to call the base class constructor explicitly.
    • Misusing private inheritance (it doesn’t allow derived-class access).
    • Overriding non-virtual methods (no runtime polymorphism).
  • Question Patterns:
    • Compare aggregation vs. inheritance (aggregation is "HAS-A"; inheritance is "IS-A").
    • Draw inheritance hierarchies with access modifiers.
    • Trace constructor/destructor calls in multilevel inheritance.

Pro Tip: Always assume the exam will ask for a code snippet with inheritance + constructor chaining or a diamond problem solution. Practice writing both!

Based on the TU BIT syllabus for Object Oriented Programming (BIT153), unit 4.

Discussion

Loading…