Inheritance and Polymorphism
The course is part of this learning path
This course is designed to enhance your object-oriented programming skills by focusing on two concepts: inheritance and polymorphism. We'll cover the key concepts and then put them to practice with a couple of demo projects towards the end of the course.
- Learn about base classes and derived classes and how they are related
- Understand how different base classes can be used to control how derived classes inherit data and behaviors from their base classes
- Understand the fundamentals of polymorphism
- Learn about enumerated types in C++
- Beginner coders, new to C++
- Developers looking to upskill by adding C++ to their CV
- College students and anyone studying C++
To get the most out of this course, you should have a basic understanding of the fundamentals of C++.
Hopefully you recall that there are three primary principles of object-oriented programming. We discussed the first of these principles, encapsulation in our section on classes and OOP. We saw how encapsulation allows us to combine data and behaviors into a single entity, an object which provides us with portability and security. In this lecture, we will formally begin our discussion of the concepts and syntax related to the second primary principle of object-oriented programming, that is, inheritance. We briefly looked at inheritance when discussing the inheritance hierarchy of exceptions in the exceptions section. We know that inheritance is a form of software we use in which methods and data are inherited by derived classes also called sub-classes or child classes from a base class, also called super class or parent class. This seeks to eliminate or at very least greatly reduce the amount of code that we have to write more than once. Before we are more formally introduced to more syntax involving inheritance, I need to formally introduce you to an access specifier, protected. We have used public and private throughout our OOP journey but haven't really used protected. The protected access specifier fits in between public and private as far as ability to access member functions and data members. If a base class or parent class has a protected member, either a field or a method, then the derived class, child class has access to it the same as if it were public. However, two functions and classes outside an inheritance hierarchy, protected numbers are not accessible, the same as if they were private. So, protected is in some ways like a mid level protection of data and methods. It isn't used nearly as often as public and private in most situations and some software engineers consider it bad style and think it is better to provide public member functions to access it in the parent class as needed. Now this brings us to the syntax and use of base class access specifiers. So, we have syntax like you see before you, class derived class inherits from, that's the column. Public base class. This is called public inheritance. This is the most common form but instead of the public keyword, keywords protected and private maybe used as well. In fact, the base class access specifier could be left off entirely in which case the default access level is private. So, we know what private protected and public meaning terms of the fields and methods in our class, but what do they mean in the context of base class access specifiers. The table on the slide you're seeing explains this. They basically act as filters for inheritance. As you can see public inheritance keeps everything the same during the inheritance. The private members aren't accessible at all from the derived class but protected in public members remain the same in the derived class as they were in the base class. With protected inheritance, the private members of the base class of course still aren't accessible to the derived class. The protected members stay the same, that is, protected. The difference is that now the members that are public in the base class are inherited but are now protected in the derived class. So, this has caused a level of reduction in access through derived classes from the public down to protected. With private inheritance as always, the base classes private members are still not accessible by the derived class at all. The protected and public members of the derived class are filtered, so to speak, and are now private members of the derived class. So, this level of base class access specification truly restricts everything except the immediate derived class from having further access through the derived class from those members inherited from the base class. For our purposes and most situations, public inheritance is by far the most popular. In fact, a lot of programming languages only have public inheritance and everything works fine. So, we will focus on public inheritance. We'll start building a base class in this lecture and then work on deriving from it in the next lecture. Make sure you are careful as these classes will continue to follow us throughout a large portion of the course. We will even use them in our polymorphism discussion. So, you should be able to see now the UML class diagram of an animal class. The getters and setters for the animal class are pretty straightforward. The name of the animal is its given name like Bob or Roger or Sally or Fido or whatever. So, the only method that might be a little bit different is makeNoise. What I'd like you to do with makeNoise is return a string representing the noise the animal makes. Now, since this class is just some generic animal, let's simply return the string unknown. And I've made the UML diagram for you so now it's your turn to take over. I have a challenge for you. Create a project called AnimalFun. I'd like you to use the UML diagram and my description of make noise to create the animal class. We aren't using inheritance just yet so this is basically just a review of basic encapsulation and class development. Make sure to write a main function and test out an instance of your animal, especially the makeNoise method that returns the string unknown. So, pause the video, come back when you're done or if you just want to see how I did it. How did that go for you? Were you able to complete the challenge? Let's work on it together. So, let's create a project called AnimalFun, empty project and we will call it AnimalFun. We'll be really careful with this because we'll be using it throughout this section. So, the first thing we'll work on is the header file, but I'll create a new item header file called Animal.h, I will create an animal.cpp to get us ready. And also another new item, main.cpp. So, main, we will fill in with our skeleton here. Alright, and inside of our Animal.h. ifndef ANIMAL_H, ANIMAL_H. So, the include guards. We're going to need string I think. Okay, class Animal, good, public. And we'll have private, okay? The private data will consist of string name, double weight, okay? And then we have Animal string name, double weight and of course, string getName and then we have double getWeight, void setName, takes a string and void setWeight, takes a double and then finally makeNoise. And since it doesn't modify any of the internal data, we can make it const. Alright, that's Animal.h. In Animal.cpp, I will just copy over all these. We have to include Animal.h of course, then we'll copy over all these and you know how I like to do it, I usually give them a body first, like this, clean them up a little bit and then I worry about the actual code. There we go. Keeps me from having to retype some of the stuff and if you get used to doing this, it becomes like second nature, it's faster than retyping it in some cases. And of course we need the name of the class and the scope resolution operator. Alright. There, there, there, setWeight and makeNoise. Good. So, inside of the constructor that takes the name and the weight, all we're going to do is we're just going to directly set the name and the weight. We could do bound checking and things like that. And if you were working on a full industrial project, you might want to do some checking to make sure that the data looks good. Okay, setName. We're more focused on the foundations. All right, now makeNoise is a little bit different, all we're doing since it's a generic animal is we can just directly return the string literal unknown. Alright. Now, we should do some testing. Make sure that's saved and inside of main, we'll do some testing. I will create an animal. We don't have to create this one dynamically, I'll say its name is Sam and it weighs 100, say, pounds. You can use kilos or whatever you'd like. Animal name, myAnimal.getName. Since it's not a pointer, we don't use the arrow. It's just an object. Animal weight, .getWeight and then Animal noise. Good. And of course, let's run it. Start without debugging. Nice. So, we can see that the name is Sam, the weight is 100 and the noise is unknown. So, the animal class works exactly like we expected. So far so good. Simple and straight to the point. Hopefully this has helped you recall some of the skills from the classes and OOP section and that you are ready for something new to build upon your skills. In the next lecture, we will implement inheritance. I'll see you there.
John has a Ph.D. in Computer Science and is a professional software engineer and consultant, as well as a computer science university professor and department chair.