🧬 Single Inheritance in C++
When One Class Learns Everything from Another
The Family Recipe Book 📖
Imagine your grandmother has a special recipe book. She knows how to make bread, soup, and cookies. Now, you want to learn cooking too! Instead of starting from zero, you inherit all her recipes. You automatically know everything she knows—plus you can add your own special dish!
This is Single Inheritance in C++. One class (you) learns from exactly one other class (grandmother).
🎯 What We’ll Learn
- Inheritance Basics
- Access Control in Inheritance
- Constructors in Inheritance
- Destructors in Inheritance
- Inheriting Constructors
1. Inheritance Basics
The Parent-Child Relationship
Think of a parent class (also called base class) as a template. The child class (also called derived class) copies everything from the parent and can add more.
Real-Life Example
A Vehicle knows how to:
- Start engine
- Stop engine
A Car is a type of vehicle. It automatically knows those things PLUS it can:
- Open trunk
- Play radio
graph TD A["🚗 Vehicle<br/>Parent Class"] --> B["🚙 Car<br/>Child Class"] A --> C["Has: startEngine"] A --> D["Has: stopEngine"] B --> E["Gets ALL from Vehicle"] B --> F["Adds: openTrunk"] B --> G["Adds: playRadio"]
Code Example
// Parent class (base class)
class Animal {
public:
void eat() {
cout << "I can eat!" << endl;
}
void sleep() {
cout << "I can sleep!" << endl;
}
};
// Child class (derived class)
class Dog : public Animal {
public:
void bark() {
cout << "Woof! Woof!" << endl;
}
};
Using It
int main() {
Dog myDog;
// From Animal (inherited)
myDog.eat(); // Works!
myDog.sleep(); // Works!
// Dog's own ability
myDog.bark(); // Works!
return 0;
}
Output:
I can eat!
I can sleep!
Woof! Woof!
The Magic Word: public
When we write class Dog : public Animal, the : public Animal part says:
“Hey Dog! Copy everything from Animal!”
2. Access Control in Inheritance
The Three Secret Levels 🔐
Not everything in a family gets passed down equally. Some things are:
- Public - Everyone can see and use
- Protected - Only family members can use
- Private - Parent keeps it secret, even from children!
The Three Access Specifiers
| Access | Parent Can Use | Child Can Use | Outsiders Can Use |
|---|---|---|---|
public |
✅ Yes | ✅ Yes | ✅ Yes |
protected |
✅ Yes | ✅ Yes | ❌ No |
private |
✅ Yes | ❌ No | ❌ No |
Simple Analogy
Think of a house:
- Public = Front yard (everyone sees it)
- Protected = Living room (only family enters)
- Private = Parent’s diary (nobody else reads it!)
Code Example
class BankAccount {
public:
string ownerName; // Anyone can see
protected:
double balance; // Only family sees
private:
string password; // Super secret!
};
class SavingsAccount : public BankAccount {
public:
void showBalance() {
cout << ownerName; // ✅ Works
cout << balance; // ✅ Works
// cout << password; // ❌ ERROR!
}
};
Types of Inheritance Access
When you inherit, you choose HOW to inherit:
class Child : public Parent // Most common
class Child : protected Parent // Less common
class Child : private Parent // Rare
Public Inheritance (Most Used):
- Public stays public
- Protected stays protected
- Private stays hidden
graph TD A["Parent&#39;s public] -->|becomes| B[Child&#39;s public"] C["Parent&#39;s protected] -->|becomes| D[Child&#39;s protected"] E[Parent's private] -->|stays| F["Hidden from Child"]
3. Constructors in Inheritance
Setting Up Both Parent and Child 🏗️
When you build a house, you first need a foundation (parent), then you add walls and roof (child).
Constructors work the same way!
The Golden Rule
Parent constructor runs FIRST, then child constructor runs.
Simple Example
class Animal {
public:
Animal() {
cout << "Animal born!" << endl;
}
};
class Dog : public Animal {
public:
Dog() {
cout << "Dog born!" << endl;
}
};
int main() {
Dog myDog;
return 0;
}
Output:
Animal born!
Dog born!
See? Animal (parent) prints first!
Passing Values to Parent Constructor
What if the parent needs information?
class Person {
protected:
string name;
public:
Person(string n) {
name = n;
cout << "Person: " << name << endl;
}
};
class Student : public Person {
private:
int grade;
public:
// Send "n" to Parent's constructor
Student(string n, int g) : Person(n) {
grade = g;
cout << "Student grade: " << grade << endl;
}
};
int main() {
Student s("Emma", 5);
return 0;
}
Output:
Person: Emma
Student grade: 5
The Magic Syntax
Student(string n, int g) : Person(n) {
// ^^^^^^^^^^^^^^^^^^^
// This part calls Parent's constructor!
}
The : Person(n) is called an initializer list. It sends data UP to the parent.
4. Destructors in Inheritance
Cleaning Up After the Party 🧹
If constructors set things up, destructors clean things up when we’re done.
The Golden Rule (Opposite!)
Child destructor runs FIRST, then parent destructor runs.
Think of it like packing up after camping:
- First, pack your personal stuff (child)
- Then, take down the main tent (parent)
Code Example
class Animal {
public:
Animal() {
cout << "Animal created" << endl;
}
~Animal() {
cout << "Animal destroyed" << endl;
}
};
class Dog : public Animal {
public:
Dog() {
cout << "Dog created" << endl;
}
~Dog() {
cout << "Dog destroyed" << endl;
}
};
int main() {
Dog myDog;
cout << "--- Program ending ---" << endl;
return 0;
}
Output:
Animal created
Dog created
--- Program ending ---
Dog destroyed
Animal destroyed
Visual Flow
graph TD subgraph Creation A["1. Animal Constructor"] --> B["2. Dog Constructor"] end subgraph Destruction C["3. Dog Destructor"] --> D["4. Animal Destructor"] end B -.-> C
Why This Order?
The child might use parent’s stuff. So:
- Build: Parent first (child might need parent’s things)
- Destroy: Child first (clean your mess before parent goes away)
5. Inheriting Constructors
Borrowing Parent’s Setup Recipes 🔧
Starting from C++11, you can directly use parent’s constructors without rewriting them!
The Problem (Before C++11)
class Shape {
public:
int x, y;
Shape(int a, int b) : x(a), y(b) {}
};
class Circle : public Shape {
public:
// Had to rewrite constructor!
Circle(int a, int b) : Shape(a, b) {}
};
The Solution: using
class Shape {
public:
int x, y;
Shape(int a, int b) : x(a), y(b) {
cout << "Shape at " << x << "," << y << endl;
}
};
class Circle : public Shape {
public:
// Magic line! Inherit ALL constructors
using Shape::Shape;
double radius = 1.0; // Circle's own data
};
int main() {
Circle c(5, 10); // Uses Shape's constructor!
return 0;
}
Output:
Shape at 5,10
What using Shape::Shape Does
It says: “Dear compiler, let Circle use any constructor that Shape has!”
Adding Your Own Data
class Vehicle {
public:
string brand;
Vehicle(string b) : brand(b) {}
};
class Car : public Vehicle {
public:
using Vehicle::Vehicle; // Inherit constructors
int wheels = 4; // Car's own member
void show() {
cout << brand << " has " << wheels << " wheels";
}
};
int main() {
Car myCar("Toyota");
myCar.show();
return 0;
}
Output:
Toyota has 4 wheels
🎉 Quick Summary
| Concept | Key Point |
|---|---|
| Basics | Child class gets everything from parent using : |
| Access Control | Public = all see, Protected = family only, Private = parent only |
| Constructors | Parent runs FIRST, then child |
| Destructors | Child runs FIRST, then parent |
| Inheriting Constructors | Use using Parent::Parent; to borrow |
🚀 You Did It!
You now understand Single Inheritance! Remember:
- Inheritance saves you from rewriting code
- The child gets parent’s abilities automatically
- Access control keeps some things private
- Constructors and destructors have opposite orders
usingkeyword lets you inherit constructors easily
Go build something amazing! 🌟
