C++ Inheritance
Creating new classes based on existing classes
🧬 What is Inheritance?
Inheritance allows creating new classes based on existing classes, inheriting properties and methods. Child classes extend parent functionality while promoting code reuse, hierarchy organization, and the "is-a" relationship concept.
// Base class
class Animal {
public:
void eat() { cout << "Eating..."; }
};
// Derived class
class Dog : public Animal {
public:
void bark() { cout << "Woof!"; }
};
Benefits:
✓ Code Reusability
✓ Hierarchical Organization
✓ Extensibility
Types of Inheritance
Single
One child inherits from one parent
class Child : public Parent {
// Child class
};
Multiple
One child inherits from multiple parents
class Child : public Parent1,
public Parent2 {
};
Multilevel
Chain of inheritance (grandparent-parent-child)
class A {};
class B : public A {};
class C : public B {};
Hybrid
Combination of multiple inheritance types
// Mix of single + multiple
class D : public B, public C {};
🔹 Single Inheritance
Single inheritance allows a derived class to inherit members and behaviors from one base class, forming an "is-a" relationship. A Car class can derive from Vehicle, inheriting methods like start() ("Vehicle starting...") and adding its own specifics like honk() ("Beep beep!") and doorCount. This promotes code reuse and logical hierarchy—a Car is a Vehicle. The output shows accessing inherited properties ("Brand: Toyota, Year: 2023") alongside derived attributes ("Doors: 4"). Single inheritance simplifies design but limits a class to one direct base, avoiding the complexity of multiple inheritance.
#include <iostream>
using namespace std;
// Base class
class Vehicle {
protected:
string brand;
int year;
public:
Vehicle(string b, int y) : brand(b), year(y) {}
void start() {
cout << "Vehicle starting..." << endl;
}
void displayInfo() {
cout << "Brand: " << brand << ", Year: " << year << endl;
}
};
// Derived class
class Car : public Vehicle {
private:
int doors;
public:
Car(string b, int y, int d) : Vehicle(b, y), doors(d) {}
void honk() {
cout << "Beep beep!" << endl;
}
void displayCarInfo() {
displayInfo(); // Inherited method
cout << "Doors: " << doors << endl;
}
};
int main() {
Car myCar("Toyota", 2023, 4);
myCar.start(); // Inherited method
myCar.honk(); // Own method
myCar.displayCarInfo();
return 0;
}
Output:
Vehicle starting...
Beep beep!
Brand: Toyota, Year: 2023
Doors: 4
🔹 Multiple Inheritance
Multiple inheritance enables a class to inherit from more than one base class, combining their capabilities. A Duck class can inherit from both Flyable (with method fly() producing "Flying in the sky!") and Swimmable (with swim() producing "Swimming in water!"), while also defining its own quack(). This models real-world objects with multiple distinct roles. However, it can introduce challenges like the diamond problem (ambiguous base paths) and increased complexity. Careful design using virtual inheritance or interfaces is needed to manage these trade-offs effectively.
#include <iostream>
using namespace std;
class Flyable {
public:
void fly() {
cout << "Flying in the sky!" << endl;
}
};
class Swimmable {
public:
void swim() {
cout << "Swimming in water!" << endl;
}
};
// Multiple inheritance
class Duck : public Flyable, public Swimmable {
public:
void quack() {
cout << "Quack quack!" << endl;
}
};
int main() {
Duck donald;
donald.fly(); // From Flyable
donald.swim(); // From Swimmable
donald.quack(); // Own method
return 0;
}
Output:
Flying in the sky!
Swimming in water!
Quack quack!
🔹 Multilevel Inheritance
Multilevel inheritance creates a chain of derived classes, each extending the previous level, to model increasingly specialized entities. For example, Vehicle → Car → SportsCar forms a hierarchy where each level adds specificity. Vehicle provides basic mobility, Car adds passenger features, and SportsCar introduces high-performance traits. This allows gradual refinement and reuse of code up the chain. While it promotes organized hierarchies, deep chains can become fragile—changes to a middle base class affect all descendants. It's best used for clear, stable "is-a-kind-of" relationships.
#include <iostream>
using namespace std;
// Grandparent class
class Animal {
public:
void breathe() {
cout << "Breathing..." << endl;
}
};
// Parent class
class Mammal : public Animal {
public:
void feedMilk() {
cout << "Feeding milk to babies" << endl;
}
};
// Child class
class Dog : public Mammal {
public:
void bark() {
cout << "Woof woof!" << endl;
}
};
int main() {
Dog myDog;
myDog.breathe(); // From Animal (grandparent)
myDog.feedMilk(); // From Mammal (parent)
myDog.bark(); // Own method
return 0;
}
Output:
Breathing...
Feeding milk to babies
Woof woof!
🔹 Virtual Inheritance
Virtual inheritance in C++ is designed to resolve the diamond problem that arises in multiple inheritance. When two parent classes inherit from a common grandparent, virtual inheritance ensures only one instance of the grandparent exists in the final derived class. This prevents ambiguous calls to inherited members and maintains a single, shared base subobject. For example, a Bat class inheriting virtually from both Mammal and Bird avoids duplicate Animal base objects, ensuring consistent behavior for methods like eat(), walk(), and fly().
#include <iostream>
using namespace std;
class Animal {
public:
void eat() {
cout << "Animal eating" << endl;
}
};
// Virtual inheritance prevents duplicate Animal copies
class Mammal : virtual public Animal {
public:
void walk() {
cout << "Walking on land" << endl;
}
};
class Bird : virtual public Animal {
public:
void fly() {
cout << "Flying in air" << endl;
}
};
// Bat inherits from both Mammal and Bird
class Bat : public Mammal, public Bird {
public:
void hangUpsideDown() {
cout << "Hanging upside down" << endl;
}
};
int main() {
Bat myBat;
myBat.eat(); // Only one Animal::eat() exists
myBat.walk(); // From Mammal
myBat.fly(); // From Bird
myBat.hangUpsideDown(); // Own method
return 0;
}
Output:
Animal eating
Walking on land
Flying in air
Hanging upside down