OOP · ENCT 151

Ch 5. Inheritance

5 hours · 7 marks

5.1 Base Class and Derived Class

Inheritance lets a new class (derived/child class) acquire the properties (data members) and behaviour (member functions) of an existing class (base/parent class), promoting code reuse.

class Animal {              // base class
public:
    void eat() { cout << "Eating..."; }
};
class Dog : public Animal {  // derived class
public:
    void bark() { cout << "Barking..."; }
};
int main() {
    Dog d;
    d.eat();   // inherited from Animal
    d.bark();  // Dog's own
}

5.2 protected Access Specifier

protected members are accessible within the class itself and within any class derived from it, but NOT from outside the class (unlike public) — this makes it the typical choice for members that a base class wants to hide from the outside world but still share with subclasses.

5.3 Derived Class Declaration

class Derived : access-specifier Base {
    // additional members
};
// example:
class Manager : public Employee { ... };

5.4 Is-a Relation and Has-a Relation

Is-a (inheritance)Has-a (composition/aggregation)
Derived class IS a specialized type of the base classA class HAS another class's object as a member
Example: Dog is an AnimalExample: Car has an Engine
Implemented via class D : public BImplemented by declaring an object as a data member

5.5 Public, Protected and Private Inheritance

The access specifier used while inheriting controls how base class members appear in the derived class:

Base memberpublic inheritanceprotected inheritanceprivate inheritance
publicpublicprotectedprivate
protectedprotectedprotectedprivate
privatenot accessiblenot accessiblenot accessible

Private members of the base class are never directly accessible in the derived class regardless of the inheritance mode — they can only be accessed indirectly through public/protected base class methods.

5.6 Member Overriding

When a derived class defines a member function with the same name and signature as one in the base class, the derived class version "hides"/overrides it for objects of the derived type.

class Base {
public:
    void show() { cout << "Base::show"; }
};
class Derived : public Base {
public:
    void show() { cout << "Derived::show"; }   // overrides/hides Base::show
    void callBase() { Base::show(); }             // explicit call to base version
};

5.7 Forms of Inheritance

5.8 Constructors in Derived Class

When a derived object is created, the base class constructor is executed first, then the derived class constructor body runs. Arguments are passed to the base constructor using a member initialization list.

class Base {
public:
    Base(int x) { cout << "Base ctor " << x; }
};
class Derived : public Base {
public:
    Derived(int x, int y) : Base(x) {    // explicitly calling base ctor
        cout << " Derived ctor " << y;
    }
};
Derived d(1, 2);  // prints: Base ctor 1  Derived ctor 2

5.9 Destructor in Derived Class

Destructors execute in the reverse order of constructors — the derived class destructor runs first, then the base class destructor.

~Derived() { cout << "Derived dtor "; }
~Base() { cout << "Base dtor"; }
// output on object destruction: Derived dtor Base dtor

5.10 Need of Virtual Base Class

In multiple/hybrid inheritance, if two base classes both inherit from a common ancestor and a further class inherits from both, the common ancestor's members get duplicated (the diamond problem), causing ambiguity.

class Person { public: string name; };
class Student : virtual public Person { };   // virtual inheritance
class Employee : virtual public Person { };
class TeachingAssistant : public Student, public Employee { };
// with 'virtual', TeachingAssistant has only ONE copy of Person's members

Declaring the common base as a virtual base class ensures only a single shared copy of it exists in the most-derived object, eliminating ambiguity and duplication.

Most Probable Questions

Q1. What is inheritance? Explain its different forms with diagrams/examples. 7 marks
Inheritance allows a derived class to reuse the properties/behaviour of a base class (see 5.1). Explain the five forms — single, multiple, multilevel, hierarchical, hybrid — each with a one-line example and a simple arrow diagram (A → B for single; A → B → C for multilevel; A → B, A → C for hierarchical). See section 5.7.
Q2. Differentiate between public, private, and protected inheritance. 6 marks
Use the visibility table in section 5.5: with public inheritance, base public/protected members keep their access level in the derived class; with protected inheritance, both become protected; with private inheritance, both become private in the derived class. Private base members are never accessible in the derived class under any inheritance mode.
Q3. What is a virtual base class? Explain the diamond problem it solves with a program. 7 marks
See section 5.10 for the diamond-problem scenario and code example. Explain: without virtual, TeachingAssistant would contain two separate copies of Person's members (one via Student, one via Employee), causing ambiguous access like ta.name. Declaring Person as a virtual base ensures a single shared copy.
Q4. Explain the order of execution of constructors and destructors in an inheritance hierarchy. 5 marks
Constructors run base-to-derived (base class constructor first, then derived). Destructors run in the exact reverse order: derived-to-base (derived class destructor first, then base). This ensures a derived object is fully built on top of a fully constructed base, and is torn down from the top of the hierarchy downward. See sections 5.8–5.9.
Q5. Differentiate between is-a and has-a relationships with examples. 4 marks
Is-a is implemented through inheritance and represents specialization (a Car is-a Vehicle). Has-a is implemented through composition/aggregation and represents ownership/containment (a Car has-a Engine). See table in section 5.4.
Q6. Write a program demonstrating multilevel inheritance where constructors of each class print a message. 6 marks
class A { public: A() { cout << "A "; } };
class B : public A { public: B() { cout << "B "; } };
class C : public B { public: C() { cout << "C "; } };
int main() { C obj; }   // Output: A B C
Q7. What is member overriding? How is it different from overloading? 4 marks
Overriding happens between a base and derived class: the derived class redefines a function with the exact same name and signature as the base class version, hiding it for derived objects (section 5.6). Overloading happens within the same class/scope: multiple functions share a name but differ in parameter list (Ch. 2). Overriding is related to inheritance; overloading is related to compile-time polymorphism.
Q8. Why is the protected access specifier needed when private and public already exist? 3 marks
private members are hidden even from derived classes, which prevents legitimate reuse of implementation details. public members are visible to everyone, breaking encapsulation. protected fills the gap: members are hidden from the outside world (like private) but still accessible to derived classes (unlike private), supporting controlled extension of a base class.
← Chapter 4 Next: Chapter 6 — Virtual Functions →