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 production_year;

bool is_cabrio;
};

struct Airplane
{
std::string brand;
std::string model;
int production_year;

int number_of_engines;
std::string airlines_name;
};

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 production_year;
};

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 is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
}
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <string>

struct Vehicle
{
std::string brand;
std::string model;
int production_year;
};

struct Car : Vehicle
{
bool is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
};

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 production_year fields as if they were directly in Car structure:

// prism-push-types:Car
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.production_year = 2010;
ford.is_cabrio = false;

The same applies to the plane:

// prism-push-types:Airplane
Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.production_year = 2010;
boeing.number_of_engines = 2;
boeing.airlines_name = "Air Canada";
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <iostream>
#include <string>

struct Vehicle
{
std::string brand;
std::string model;
int production_year;
};

struct Car : Vehicle
{
bool is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
};

int main()
{
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.production_year = 2010;
ford.is_cabrio = false;

Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.production_year = 2010;
boeing.number_of_engines = 2;
boeing.airlines_name = "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 complete_name() method to the Vehicle class which will return the name consisiting of brand and model:

struct Vehicle 
{
// ...

std::string complete_name()
{
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.complete_name(); // "Ford Fiesta"
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <iostream>
#include <string>

struct Vehicle
{
std::string brand;
std::string model;
int production_year;

std::string complete_name()
{
return brand + " " + model;
}
};

struct Car : Vehicle
{
bool is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
};

int main()
{
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.production_year = 2010;
ford.is_cabrio = false;

Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.production_year = 2010;
boeing.number_of_engines = 2;
boeing.airlines_name = "Air Canada";

std::cout << ford.complete_name() << '\n'; // "Ford Fiesta"
std::cout << boeing.complete_name() << '\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 production_year;

bool is_cabrio;
};

struct Airplane
{
std::string brand;
std::string model;
int production_year;

int number_of_engines;
std::string airlines_name;
};

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 production_year;
};

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 is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
}
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <string>

struct Vehicle
{
std::string brand;
std::string model;
int production_year;
};

struct Car : Vehicle
{
bool is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
};

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 production_year fields as if they were directly in Car structure:

// prism-push-types:Car
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.production_year = 2010;
ford.is_cabrio = false;

The same applies to the plane:

// prism-push-types:Airplane
Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.production_year = 2010;
boeing.number_of_engines = 2;
boeing.airlines_name = "Air Canada";
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <iostream>
#include <string>

struct Vehicle
{
std::string brand;
std::string model;
int production_year;
};

struct Car : Vehicle
{
bool is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
};

int main()
{
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.production_year = 2010;
ford.is_cabrio = false;

Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.production_year = 2010;
boeing.number_of_engines = 2;
boeing.airlines_name = "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 complete_name() method to the Vehicle class which will return the name consisiting of brand and model:

struct Vehicle 
{
// ...

std::string complete_name()
{
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.complete_name(); // "Ford Fiesta"
See full code
// prism-push-types:Vehicle,Car,Airplane
#include <iostream>
#include <string>

struct Vehicle
{
std::string brand;
std::string model;
int production_year;

std::string complete_name()
{
return brand + " " + model;
}
};

struct Car : Vehicle
{
bool is_cabrio;
};

struct Airplane : Vehicle
{
int number_of_engines;
std::string airlines_name;
};

int main()
{
Car ford;
ford.brand = "Ford";
ford.model = "Fiesta";
ford.production_year = 2010;
ford.is_cabrio = false;

Airplane boeing;
boeing.brand = "Boeing";
boeing.model = "737";
boeing.production_year = 2010;
boeing.number_of_engines = 2;
boeing.airlines_name = "Air Canada";

std::cout << ford.complete_name() << '\n'; // "Ford Fiesta"
std::cout << boeing.complete_name() << '\n'; // "Boeing 737"
}