Skip to main content

Inheritance

caution

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;
Instance of a base structure

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
}
The order of definitions

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"
}

Inheritance

caution

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;
Instance of a base structure

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
}
The order of definitions

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"
}