When we start implementing more complex systems using classes, we quickly encounter a problem. We'll have multiple types of objects that have a lot of similar requirements. However, they're not so similar that we'd want them to both share the exact same class.
For example, lets imagine a future where we are trying to create three types of objects: rocks, goblins and dragons.
The Rocks just need one ability:
The Goblins need these abilities:
The Dragons need these abilities:
Trying to model these as a single class is problematic. The class would be very complex. Additionally, most of our objects would be carrying around a lot of variables they will never use.
The ability to move would require variables to control things like movement speed. Having every rock carry around those variable seems like a waste of memory.
Equally, trying to create three totally separate classes for these objects isn't ideal. We'd end up having our render code repeated in 3 classes, and that will only get worse as we add more.
Fortunately, this situation is exactly what inheritance is designed to solve.
Inheritance allows to organise our classes into hierarchies. This allows a class to inherit the functions and variables of its parent. For example, lets create a class that we could use to create our rock objects. We'll call this the
An actor is a common name for any simple class of things that can exist in our imagined world. It is where we will define the
Next, lets create a class for our Goblins. Goblins also need the ability to be rendered, but with inheritance, we no longer need to recreate that functionality.
Actor already has that ability.
Goblins are just a more specific type of
Actor, so we can have our
Goblin class inherit all the abilities of the
Goblin class has the
Render ability, without needing to write any additional code. It just inherits it from the parent class.
Hierarchical structures like these are very common in programming. There are many different terms used to describe the position of something within the hierarchy.
Phrases associated with family relationships are often used, such as parent, child, ancestor, descendant and more. For example:
Actoris a parent or an ancestor of
Goblinis a child or a descendant of
Other popular terms include _sub class, base class and derived class. For example:
Goblinis a sub class of
Actoris the base class of
This tree structure provides our classes with a powerful ability. We get to have our dedicated, specific classes, but they don't need to duplicate the more generic, shared functions. They can instead just inherit those functions and variables from their ancestors.
What is inheritance?
In our above example, lets imagine we create an object from our Goblin class.
Bonker is a Goblin, ie, it is an instance of the
Goblin class, therefore, it has access to the
Attack() function, as we've seen before.
The cool thing with inheritance is that, because the Goblin class is a child of the Actor class, all Goblin objects are also Actor objects. This means that Goblins have access to all the functions and variables of the Actor class, too.
Goblin Bonker; // Available because Bonker is an Actor Bonker.Render(); // Available because Bonker is a Goblin Bonker.Attack();
So, with this class hierarchy, all Goblin objects are inherently also Actor objects. The opposite is not necessarily true - an Actor is not necessarily also a Goblin. It could just be a plain Actor, or it could be some other subclass of actor.
Actor BigRock; // Available because BigRock is an Actor BigRock.Render(); // But we can't do this, because BigRock is not a Goblin BigRock.Attack();
If we have a
Dog class that inherits from the
Animal class, and we create a new object of type
Dog, which of the following is true?
If we have a
Dog class that inherits from the
Animal class, and we try to create a new object using the
Animal class, which of the following is true?
We haven't yet implemented our original design yet. Lets add the Dragon class, using the same approach:
Something should seem off here. The Dragon and Goblin classes both have the
DropLoot functions. That's too much duplicate code.
Thankfully, with our new knowledge of inheritance, we might realise a way we can improve this design.
We shouldn't move that code into the
Actor class, because simple objects like rocks don't need it. Instead, we can move that shared code into a new class. We can have both Goblin and Dragon inherit from it. Lets call this new class
Now, we have multiple layers of inheritance. With this setup, any Dragon we create will have the abilities of three different types:
Dragon Dave; // Dave is an Actor Dave.Render(); // And a Character Dave.Attack(); // And a Dragon Dave.Fly();
That's enough theory for now - lets see how we can unlock the possibilities of inheritance.
We'll set up the above hierarchy in our code in the next lesson!
Become a software engineer with C++. Starting from the basics, we guide you step by step along the way