Inheritance in C++ allows you to create new classes based on existing classes, promoting code reuse and supporting specialization and generalization. There are several types of inheritance relationships that can be established between classes. Let's explore each type of inheritance and provide real-time examples for better understanding.
Single inheritance refers to the inheritance of properties and behavior from a single base class. It is the most common type of inheritance relationship. Here's an example:
#include <iostream>
// Base class
class Vehicle {
protected:
std::string brand;
public:
Vehicle(const std::string& b) : brand(b) {}
void displayBrand() {
std::cout << "Brand: " << brand << std::endl;
}
};
// Derived class
class Car : public Vehicle {
private:
int numDoors;
public:
Car(const std::string& b, int doors) : Vehicle(b), numDoors(doors) {}
void displayInfo() {
std::cout << "Car information" << std::endl;
displayBrand();
std::cout << "Number of doors: " << numDoors << std::endl;
}
};
int main() {
Car myCar("Toyota", 4);
myCar.displayInfo();
return 0;
}
In this example, the Car
class is derived from the Vehicle
base class using single inheritance. The Car
class inherits the brand member and the displayBrand()
function from the Vehicle
class. It also adds an additional member numDoors
to represent the number of doors in the car. The displayInfo() function in the Car
class displays the brand and the number of doors of the car.
Multiple Inheritance refers to inheriting properties and behavior from multiple base classes. It allows a derived class to inherit from multiple base classes simultaneously. Here's an example:
#include <iostream>
// Base class 1
class Vehicle {
protected:
std::string brand;
public:
Vehicle(const std::string& b) : brand(b) {}
void displayBrand() {
std::cout << "Brand: " << brand << std::endl;
}
};
// Base class 2
class Engine {
protected:
std::string type;
public:
Engine(const std::string& t) : type(t) {}
void displayType() {
std::cout << "Engine Type: " << type << std::endl;
}
};
// Derived class
class Car : public Vehicle, public Engine {
private:
int numDoors;
public:
Car(const std::string& b, const std::string& t, int doors)
: Vehicle(b), Engine(t), numDoors(doors) {}
void displayInfo() {
std::cout << "Car information" << std::endl;
displayBrand();
displayType();
std::cout << "Number of doors: " << numDoors << std::endl;
}
};
int main() {
Car myCar("Toyota", "Petrol", 4);
myCar.displayInfo();
return 0;
}
In this example, the Car
class is derived from both the Vehicle
and Engine
base classes using multiple inheritance. The Car
class inherits the brand
member and the displayBrand()
function from the Vehicle
class, as well as the type member and the displayType()
function from the Engine class. It also adds an additional member numDoors
to represent the number of doors in the car. The displayInfo()
function in the Car
class displays the brand, engine type, and number of doors of the car.
Multilevel inheritance refers to a chain of inheritance, where a derived class becomes the base class for another derived class. This allows for hierarchical relationships between classes. Here's an example:
#include <iostream>
// Base class
class Vehicle {
protected:
std::string brand;
public:
Vehicle(const std::string& b) : brand(b) {}
void displayBrand() {
std::cout << "Brand: " << brand << std::endl;
}
};
// Intermediate derived class
class Car : public Vehicle {
private:
int numDoors;
public:
Car(const std::string& b, int doors) : Vehicle(b), numDoors(doors) {}
void displayInfo() {
std::cout << "Car information" << std::endl;
displayBrand();
std::cout << "Number of doors: " << numDoors << std::endl;
}
};
// Derived class
class SportsCar : public Car {
private:
std::string type;
public:
SportsCar(const std::string& b, int doors, const std::string& t)
: Car(b, doors), type(t) {}
void displayInfo() {
std::cout << "Sports Car information" << std::endl;
displayBrand();
std::cout << "Number of doors: " << numDoors << std::endl;
std::cout << "Type: " << type << std::endl;
}
};
int main() {
SportsCar myCar("Ferrari", 2, "Convertible");
myCar.displayInfo();
return 0;
}
In this example, the SportsCar
class is derived from the Car
class, which itself is derived from the Vehicle
base class. This establishes a multilevel inheritance relationship. The SportsCar
class inherits the brand
member and the displayBrand()
function from the Vehicle
class, as well as the numDoors
member and the displayInfo()
function from the Car
class. It also adds an additional member type to represent the type of sports car. The displayInfo()
function in the SportsCar
class displays the brand, number of doors, and type of the sports car.
Hierarchical inheritance refers to a situation where multiple derived classes are created from a single base class. Each derived class has its own specialized features and behavior. Here's an example:
#include <iostream>
// Base class
class Shape {
public:
virtual void display() {
std::cout << "This is a shape." << std::endl;
}
};
// Derived class 1
class Circle : public Shape {
public:
void display() override {
std::cout << "This is a circle." << std::endl;
}
};
// Derived class 2
class Rectangle : public Shape {
public:
void display() override {
std::cout << "This is a rectangle." << std::endl;
}
};
int main() {
Circle myCircle;
Rectangle myRectangle;
myCircle.display(); // Output: This is a circle.
myRectangle.display(); // Output: This is a rectangle.
return 0;
}
In this example, the Circle
and Rectangle
classes are derived from the Shape
base class using hierarchical inheritance. Each derived class provides its own implementation of the display()
function, which overrides the virtual function in the base class. This allows each derived class to have its own specialized behavior while inheriting common properties and functions from the base class.
Hybrid inheritance refers to a combination of different types of inheritance. It involves the inheritance of multiple base classes using a combination of single, multiple, multilevel, or hierarchical inheritance. Let's consider an example to understand hybrid inheritance:
#include <iostream>
// Base class 1
class Shape {
public:
virtual void display() {
std::cout << "This is a shape." << std::endl;
}
};
// Base class 2
class Drawable {
public:
virtual void draw() {
std::cout << "Drawing the shape." << std::endl;
}
};
// Derived class 1 with multiple inheritance
class Circle : public Shape, public Drawable {
public:
void display() override {
std::cout << "This is a circle." << std::endl;
}
void draw() override {
std::cout << "Drawing a circle." << std::endl;
}
};
// Derived class 2 with single inheritance
class Cylinder : public Circle {
public:
void display() override {
std::cout << "This is a cylinder." << std::endl;
}
};
int main() {
Circle myCircle;
Cylinder myCylinder;
myCircle.display(); // Output: This is a circle.
myCircle.draw(); // Output: Drawing a circle.
std::cout << std::endl;
myCylinder.display(); // Output: This is a cylinder.
myCylinder.draw(); // Output: Drawing a circle.
return 0;
}
In this example, we have a combination of multiple inheritance and single inheritance, resulting in hybrid inheritance.
The Circle
class is derived from both the Shape
and Drawable
base classes using multiple inheritance. It inherits the display()
function from the Shape class and the draw()
function from the Drawable
class. It provides its own implementations of these functions.
The Cylinder
class is derived from the Circle
class using single inheritance. It further specializes in the Circle
class by overriding the display()
function.
In the main()
function, we create objects of both the Circle
and Cylinder
classes and demonstrate how the functions from different base classes are inherited and used. The output demonstrates the behavior of each class and the combination of inheritance relationships.
Hybrid inheritance allows you to combine the benefits of multiple inheritance relationships, enabling you to create complex class hierarchies with different levels of specialization and code reuse.
By utilizing different types of inheritance, you can create class hierarchies and establish relationships between classes to model real-world scenarios and promote code reuse and flexibility in your C++ programs.