Inheritance
Note, this article is not finished! You can help by editing this doc page.
In this lesson you will learn how to use inheritance in order to share properties and characteristic from other classes by building class hierarchy and prevent redundant code.
Motivation
When creating data structures that mimic real world elements, we often encounter situation when two such structures share common properties. For an example if we make game with vehicles containing planes ✈ and cars 🚗, we would create two structures like this:
struct Car
{
std::string brand;
std::string model;
int productionYear;
bool isCabrio;
};
struct Airplane
{
std::string brand;
std::string model;
int productionYear;
int enginesNumber;
std::string airlinesName;
};
Note the highlighted lines. After a brief analysis we can spot, that both structures share these common properties:
- brand
- model
- production year
Later in this lesson we will use inheritance to connect these structures two structures with a common base structure.
Base structure
Now when we pointed out common properties we can create structure that will consist only of these fields:
struct Vehicle
{
std::string brand;
std::string model;
int productionYear;
};
Note the name - Vehicle
. It's a structure describing general form of a vehicle. Creating an instance of such structure doesn't have much sense:
// prism-push-types:Vehicle
Vehicle vehicle;
The above code won't result in a compilation error. In the future we will learn how to prevent others from creating an instance of such object by using private constructors.
Instead of this, we will use Vehicle
to make Car
and Airplane
structures so they inherit its properties.
Derived structures
In order to create derived structres using inheritance, we have to put the base structure name after the colon:
struct Car : Vehicle
{
bool isCabrio;
};
struct Airplane : Vehicle
{
int enginesNumber;
std::string airlinesName;
}
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <string>
struct Vehicle
{
std::string brand;
std::string model;
int productionYear;
};
struct Car : Vehicle
{
bool isCabrio;
};
struct Airplane : Vehicle
{
int enginesNumber;
std::string airlinesName;
};
int main()
{
// empty for now
}
We have to place the Vehicle
definition before the derived structures definitions.
Usage
The above scheme shows, that properties inherited from Vehicle
are in both Car
and Airplane
structures.
Because of this, when we create a car inside our code, we can use brand
, model
and productionYear
fields as if they were directly in Car
structure:
// prism-push-types:Car
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.productionYear = 2010;
ford.isCabrio = false;
The same applies to the plane:
// prism-push-types:Airplane
Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.productionYear = 2010;
boeing.enginesNumber = 2;
boeing.airlinesName = "Air Canada";
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <iostream>
#include <string>
struct Vehicle
{
std::string brand;
std::string model;
int productionYear;
};
struct Car : Vehicle
{
bool isCabrio;
};
struct Airplane : Vehicle
{
int enginesNumber;
std::string airlinesName;
};
int main()
{
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.productionYear = 2010;
ford.isCabrio = false;
Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.productionYear = 2010;
boeing.enginesNumber = 2;
boeing.airlinesName = "Air Canada";
std::cout << ford.brand << '\n'; // "Ford"
std::cout << boeing.brand << '\n'; // "Boeing"
}
Inheriting methods
Just like member variables, methods are also inherited. Let's add completeName()
method to the Vehicle
class which will return the name consisiting of brand
and model
:
struct Vehicle
{
// ...
std::string completeName()
{
return brand + " " + model;
}
};
Now we can use this method on the Car
instance:
// prism-push-types:Car
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
std::cout << ford.completeName(); // "Ford Fiesta"
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <iostream>
#include <string>
struct Vehicle
{
std::string brand;
std::string model;
int productionYear;
std::string completeName()
{
return brand + " " + model;
}
};
struct Car : Vehicle
{
bool isCabrio;
};
struct Airplane : Vehicle
{
int enginesNumber;
std::string airlinesName;
};
int main()
{
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.productionYear = 2010;
ford.isCabrio = false;
Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.productionYear = 2010;
boeing.enginesNumber = 2;
boeing.airlinesName = "Air Canada";
std::cout << ford.completeName() << '\n'; // "Ford Fiesta"
std::cout << boeing.completeName() << '\n'; // "Boeing 737"
}