How to Use Inheritance and Abstraction in C++

inheritance-abstraction

In this tutorial, we will explore inheritance and abstraction in C++.

Prerequisites

Implementing Inheritance

Let’s explore one of the fundamental concepts of object-oriented programming in C++: inheritance. Inheritance enables us to derive new classes from existing ones, facilitating code reuse and simplifying the management of complex robotic software systems.

Open a terminal window, and type this:

cd ~/Documents/cpp_tutorial
code .

We’ll demonstrate how inheritance can be effectively used to model different types of sensors in robotics, such as temperature sensors and distance sensors, which share common features but also exhibit unique behaviors.

Let’s create a new C++ file and name it robot_sensors_inheritance.cpp.

Type the following code into the editor:

#include <iostream>

// Base class
class Sensor {
public:
    virtual void readData() = 0;  // Pure virtual function making Sensor an abstract class
};

// Derived class for temperature sensor
class TemperatureSensor : public Sensor {
public:
    void readData() override {
        std::cout << "Reading temperature data..." << std::endl;
    }
};

// Derived class for distance sensor
class DistanceSensor : public Sensor {
public:
    void readData() override {
        std::cout << "Reading distance data..." << std::endl;
    }
};

void testSensor(Sensor& sensor) {
    sensor.readData();  // Demonstrating polymorphic behavior
}

int main() {
    TemperatureSensor temp_sensor;
    DistanceSensor dist_sensor;

    testSensor(temp_sensor);
    testSensor(dist_sensor);

    return 0;
}

This code establishes a base class called Sensor with a virtual function readData(). 

We then create two derived classes, TemperatureSensor and DistanceSensor, each overriding the readData() method to perform their specific type of data reading. The testSensor function takes a reference to a Sensor, demonstrating polymorphism by allowing either sensor type to be tested interchangeably.

Run the code.

1-robot-sensors-inheritance

You should see “Reading temperature data…” followed by “Reading distance data…”, showing how our inheritance structure allows different sensor behaviors through a common interface.

Creating Objects

Let’s focus on one of the foundational skills in C++ programming—creating objects. Objects are instances of classes and are central to almost every C++ application, including robotics, where they represent and manage various hardware and software components.

We’ll walk through an example to illustrate the process of creating objects from a class.

Now, let’s create a new C++ file and name it creating_objects.cpp.

Type the following code into the editor:

#include <iostream>

// Define a class called Robot
class Robot {
public:
    // Constructor that prints a message when a Robot object is created
    Robot() {
        std::cout << "Robot object created." << std::endl;
    }
};

int main() {
    Robot my_robot;  // Creating an object of the Robot class
    return 0;
}

In this code, we define a class named Robot. The class includes a constructor, which is a special function that runs whenever a new object of the class is created. 

Here, the constructor prints a message to the console. 

In the main function, we create an object called my_robot from the Robot class, which triggers the constructor and its print statement.

Run the code.

2-creating-a-class

You should see the message “Robot object created.” indicating that our Robot object was successfully instantiated.

This example demonstrates the basic process of creating objects in C++. Understanding how to instantiate and use objects is essential for developing more complex robotic systems.

Defining Abstract Classes

Let’s explore the concept of abstract classes in C++ and how they can be applied in robotics projects. 

Abstract classes provide a blueprint for derived classes and enforce the implementation of certain methods, ensuring a consistent interface across related classes.

Let’s create a new C++ file and name it robot_abstract_class.cpp.

Type the following code into the editor:

#include <iostream>

class Robot {
public:
    virtual void move() = 0;
    virtual void sense() = 0;
};

class MobileRobot : public Robot {
public:
    void move() override {
        std::cout << "Mobile robot is moving." << std::endl;
    }

    void sense() override {
        std::cout << "Mobile robot is sensing its environment." << std::endl;
    }
};

int main() {
    MobileRobot mobile_robot;
    mobile_robot.move();
    mobile_robot.sense();
    return 0;
}

In this code, we define an abstract base class called Robot. It contains two pure virtual functions: move() and sense(). These functions have no implementation in the base class and must be overridden by derived classes.

We then create a derived class called MobileRobot that inherits from the Robot class. The MobileRobot class provides implementations for the move() and sense() functions, which are specific to mobile robots.

In the main() function, we create an instance of the MobileRobot class called mobile_robot. We then call the move() and sense() functions on this object.

Run the code.

3-robot-abstract-class

You should see the output indicating that the mobile robot is moving and sensing its environment.

This example demonstrates how abstract classes can be used to define a common interface for related classes in robotics. By enforcing the implementation of certain methods, abstract classes ensure that derived classes adhere to a specific contract, making the code more modular and maintainable.

Overriding Functions

Let’s explore the concept of function overriding in C++ and how it can be applied in robotics projects. 

Function overriding allows derived classes to provide their own implementation of functions defined in the base class, enabling polymorphic behavior.

Let’s create a new C++ file and name it robot_function_overriding.cpp.

Type the following code into the editor:

#include <iostream>

class Robot {
public:
    virtual void introduce() {
        std::cout << "I am a robot." << std::endl;
    }
};

class IndustrialRobot : public Robot {
public:
    void introduce() override {
        std::cout << "I am an industrial robot." << std::endl;
    }
};

int main() {
    Robot* robot = new Robot();
    IndustrialRobot* industrial_robot = new IndustrialRobot();

    robot->introduce();
    industrial_robot->introduce();

    delete robot;
    delete industrial_robot;

    return 0;
}

In this code, we define a base class called Robot with a virtual function introduce(). The introduce() function in the base class prints a generic introduction message.

We then create a derived class called IndustrialRobot that inherits from the Robot class. The IndustrialRobot class overrides the introduce() function to provide its own implementation specific to industrial robots.

In the main() function, we create pointers to objects of both the base class (Robot) and the derived class (IndustrialRobot). 

We then call the introduce() function on each object using the pointer.

Run the code.

4-function-overriding

You should see the output showing the different introduction messages for the base class and the derived class.

This example demonstrates how function overriding allows derived classes to provide their own implementation of functions defined in the base class. By marking the base class function as virtual, we enable polymorphic behavior, allowing the appropriate function to be called based on the actual object type at runtime.

Thanks, and I’ll see you in the next tutorial.

Keep building!