Inheritance is a fundamental concept in object-oriented programming (OOP) that allows you to create a new class, known as a derived class or subclass, from an existing class, called the base class or superclass. This relationship forms what is commonly referred to as an "is-a" relationship, where the derived class inherits properties and behaviors from the base class.
Understanding inheritance is crucial because it promotes code reusability, hierarchical classification of classes, and supports polymorphism, which is a core feature of OOP that enables objects to be treated as instances of their parent class. In this tutorial, we will explore the basics of inheritance in C++, including how to define base and derived classes, the syntax for inheritance, and the order of constructor and destructor calls.
A base class is a class from which other classes are derived. It contains properties and methods that can be inherited by derived classes. A derived class, on the other hand, is a class that inherits properties and methods from a base class. The derived class can extend or modify the behavior of the base class.
Think of inheritance as a family tree. In this analogy, the base class is like an ancestor (e.g., Grandparent), and the derived classes are like children who inherit traits and characteristics from their ancestors.
In C++, you can define a derived class by specifying the base class in the class declaration using the colon (:) followed by the access specifier (public, protected, or private) and the name of the base class. Here is the basic syntax:
1class BaseClass {2// Base class members3};45class DerivedClass : public BaseClass {6// Derived class members7};
Let's define a simple Animal base class and a Dog derived class.
1#include <iostream>2using namespace std;34class Animal {5public:6void eat() {7cout << "This animal eats food." << endl;8}9};1011class Dog : public Animal {12public:13void bark() {14cout << "The dog barks." << endl;15}16};1718int main() {19Dog myDog;20myDog.eat(); // Inherited method21myDog.bark(); // Derived class method22return 0;23}
This animal eats food. The dog barks.
In this example, the Dog class inherits the eat() method from the Animal base class. The Dog class also has its own method, bark(), which is specific to dogs.
When an object of a derived class is created, constructors are called in a specific order: first, the constructor of the base class is called, followed by the constructor of the derived class. Similarly, when an object is destroyed, destructors are called in reverse order: first, the destructor of the derived class, and then the destructor of the base class.
Let's modify the previous example to include constructors and destructors for both classes.
1#include <iostream>2using namespace std;34class Animal {5public:6Animal() {7cout << "Animal constructor called." << endl;8}9~Animal() {10cout << "Animal destructor called." << endl;11}12};1314class Dog : public Animal {15public:16Dog() {17cout << "Dog constructor called." << endl;18}19~Dog() {20cout << "Dog destructor called." << endl;21}22};2324int main() {25Dog myDog;26return 0;27}
Animal constructor called. Dog constructor called. Dog destructor called. Animal destructor called.
In this example, the Animal constructor is called first, followed by the Dog constructor. When the program exits, the Dog destructor is called first, followed by the Animal destructor.
Access specifiers (public, protected, and private) play a crucial role in inheritance. They determine how members of the base class are accessible to the derived class.
Let's modify the Animal class to use different access specifiers.
1#include <iostream>2using namespace std;34class Animal {5public:6void eat() {7cout << "This animal eats food." << endl;8}9protected:10void sleep() {11cout << "This animal sleeps." << endl;12}13private:14void breathe() {15cout << "This animal breathes." << endl;16}17};1819class Dog : public Animal {20public:21void display() {22eat(); // Accessible23sleep(); // Accessible24// breathe(); // Error: cannot access private member25}26};2728int main() {29Dog myDog;30myDog.display();31return 0;32}
This animal eats food. This animal sleeps.
In this example, the eat() method is public and accessible by the Dog class. The sleep() method is protected and also accessible by the Dog class. The breathe() method is private and cannot be accessed by the Dog class.
Let's create a more practical example that demonstrates inheritance with multiple classes and different access specifiers.
1#include <iostream>2using namespace std;34class Vehicle {5public:6Vehicle() {7cout << "Vehicle constructor called." << endl;8}9~Vehicle() {10cout << "Vehicle destructor called." << endl;11}12void startEngine() {13cout << "Engine started." << endl;14}15protected:16int wheels;17private:18string engineType;19};2021class Car : public Vehicle {22public:23Car() : wheels(4), engineType("Petrol") {24cout << "Car constructor called." << endl;25}26~Car() {27cout << "Car destructor called." << endl;28}29void displayInfo() {30cout << "Number of wheels: " << wheels << endl;31// cout << "Engine type: " << engineType << endl; // Error: cannot access private member32}33};3435class Motorcycle : public Vehicle {36public:37Motorcycle() : wheels(2), engineType("Petrol") {38cout << "Motorcycle constructor called." << endl;39}40~Motorcycle() {41cout << "Motorcycle destructor called." << endl;42}43void displayInfo() {44cout << "Number of wheels: " << wheels << endl;45// cout << "Engine type: " << engineType << endl; // Error: cannot access private member46}47};4849int main() {50Car myCar;51myCar.startEngine();52myCar.displayInfo();5354Motorcycle myMotorcycle;55myMotorcycle.startEngine();56myMotorcycle.displayInfo();5758return 0;59}
Vehicle constructor called. Car constructor called. Engine started. Number of wheels: 4 Vehicle destructor called. Car destructor called. Vehicle constructor called. Motorcycle constructor called. Engine started. Number of wheels: 2 Vehicle destructor called. Motorcycle destructor called.
In this example, we have a Vehicle base class and two derived classes, Car and Motorcycle. Both derived classes inherit the startEngine() method from the Vehicle class. The constructors for each class initialize the wheels member variable and set the engineType to "Petrol". The destructors are called in reverse order when the program exits.
| Concept | Description |
|---|---|
| Base Class | A class from which other classes inherit. |
| Derived Class | A class that inherits properties and methods from a base class. |
| Syntax | class DerivedClass : public BaseClass { ... }; |
| Constructor Order | Base class constructor -> Derived class constructor |
| Destructor Order | Derived class destructor -> Base class destructor |
| Access Specifiers | Public, Protected, and Private determine member accessibility in inheritance. |
In the next tutorial, we will explore different types of inheritance in C++, including public, protected, and private inheritance. Understanding these types is crucial for controlling the visibility of base class members in derived classes. Stay tuned!