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++.
In the last lecture, we learned about different base class access specifiers and what the implications are for our inheritance implementations. We also discussed how public inheritance is the most common form of inheritance. So, we will focus on that in this section. We prepared an Animal class with simple data, name, and weight and setters and getters for the data along with the constructor and makeNoise method that returns unknown. In this lecture, we will use inheritance to extend the capabilities of our Animal class with a Dog class. So, you can see the diagram right now of our Dog class and its relationship to the base class Animal. The Dog class inherits the public methods from Animal class. The only way to access the name and weight private fields or data members is through the public methods of the Animal class. Now, Dog will have everything that Animal has and more. It has an immutable field, breed, that has a corresponding getter but doesn't allow changing the breed once it is set in the constructor. The Dog class also provides a behavior that the base class Animal doesn't have. The digHole method will simply print to the console something like, "I'm digging a hole!". So, let's add the Dog class to the AnimalFun project that we were working on in the last lecture. All right, so, we have main Animal.cpp and Animal.h. We will add a header file for the Dog. So, newItem, header file, and we will call it Dog.h. And also we will have New Item, Dog.cpp. All right, so let's create our DOG_H define DOG_H and then endif. Here we go. We need string for sure. And in order to inherit from Animal, I actually need to include Animal.h using namespace std. Now I have class Dog and the syntax we saw before public inheritance from Animal. So, everything that's public stays public, everything that's private is not accessible and we don't have any protected members. So, public section in Dog, and there will also be a private section in Dog as well. Let's tap those in. So, Dog (string name, double weight, string breed). We also have getBreed which doesn't modify anything, so it's const. void digHole const and then private string breed. Excellent. So, now we will go over to Dog.cpp. So, we have to include Dog.h. We also have to include iostream and using namespace std and I like to copy over the member functions or methods that we're going to be implementing. So, give them bodies right here and then name of the class and the scope resolution operator right there and there, so all three of them. Awesome. Now, for the Dog, I can't just say, for the constructor rather for the Dog, I can't just say this name = it's even trying to change it for me. If I try this, I'm going to to get an error. So, it says remember Animal name and then it tells me it's in the Animal class is inaccessible. Even though we are a child class or a derived class, we do not have access to Animal's private data members. So, how do we pass this on to Animal? Well, you can use its member functions and you can also use the same technique we did when we used the exceptions that we had runtime error. Since Animal's constructor takes name and weight, I can pass both of those on to Animal, so int can take care of this. Now, let's make sure public Animal, good. Okay. Now, the only thing we can set for Dog because it's part of our data is the breed. Pretty cool. So, with getBreed, all I have to do is return the breed, there's no conflict and then digHole is simple, it just says, "I'm digging a hole!". All right. Now, we probably want to do a little bit of a test using main. All right, so here is our main, we have Animal.h included but we also want to use Dog, so we'll have Dog.h right there. We already have our animal named Sam, I'm going to make a dog named Rover and £80 and it's a Greyhound, kind of, a little Greyhound. All right. So, let's say Dog's name dog.getName. See? We can call getName, even though we did not define it in the Dog class; we've inherited it, so it will do exactly what Animal's version of getName does. We didn't redefine it or tell it to do anything else, we're using it directly, getWeight endl Dog's noise and then that's dog.get or makeNoise rather makeNoise and then, of course, dog.digHole that's not, it doesn't return a string, so it doesn't make sense for us to put it in the cout here because it already prints to console within that function itself. All right, so let's run it and see what we get. Okay. Good. We have Dog's named Rover, weight is 80, noise is unknown, and I'm digging a hole. Nice. So, we inherit the getName, getWeight, and makeNoise methods from Animal. We also are able to call the digHole method which is specific to Dog, so we've extended it. Almost everything looks great except maybe we want our dog to have a different behavior when makeNoise is called. Instead of unknown, maybe I want the dog object to go woof, woof woof or whatever the onomatopoeia of dog is in your language. So, bark bark, woof woof, different noises like that. So, let's add a makeNoise method to our Dog class with the same signature as it appears in Animal. So, in Dog.h, I'm going to put string and then makeNoise const. It's going to look exactly the same as it does in Animal, and then I'm going to implement it in here, okay. So, string and then Dog, there we go. makeNoise and instead of returning unknown, I'm going to return "woof!" like that. And, of course, let's run it again and see if we get different behavior. We didn't change main you'll remember, but you'll notice that now, even though the Animal's noise is unknown, Dog now goes woof, interesting. So, what we did here is called method overriding. It's different from function or method overloading in which you use the same name for a function but different signatures, different signatures for overloading, that is, parameter lists with method overriding it can only occur in an inheritance hierarchy. And the function signature must be identical between the base class, such as Animal and the derived class, such as Dog. Then when we call makeNoise on our Dog object, the Dog version of makeNoise with a woof is called. Well, we've learned a ton in this lecture. Before we move on, I want to issue you a challenge. I'd like you to extend the Dog class with a chaseCat method. It should be parameter lists and void that just prints to the console: "Here, kitty, kitty!". Make sure to test it inside main as well. So, pause the video and come back when you're done or if you need some help. How did that go for you? Were you able to complete this little challenge? Let's do it together. So, in Dog.h, we will add void chaseCat const. And then, of course, I'll copy that. Go over to Dog.cpp and then we'll paste it there. Here we go. And now, we'll put cout "Here, kitty kitty!". All right. And now, of course, we have to test it out in the main.cpp. So, under digHole, maybe we'll put dog.chaseCat. Again, it's void, it already prints to the console, doesn't return a string, so we don't use it within the cout, like we do for makeNoise, getWeight, getName, etc. So, of course, let's test it out. Debug, Start Without Debugging and see what we got. There we go. After he digs a hole, after he goes woof, then digs a hole, he then goes here, kitty kitty. So, it seems to work pretty well. I hope you were able to solve that one. If not, maybe do a little review of some of the classes and OOP section, then come back. Having solid skills and class construction and usage is very important. As a side note, C++ does allow for something called multiple inheritance, which means we can have a derived class that inherits from multiple base classes. However, this type of inheritance is often avoided because it leads to some bad coding practices and many different kinds of conflicts. So, we won't really spend time discussing it here. I want you to learn better coding practices and conventions in this course. In the next lecture, we discussed the third primary principle of object oriented programming, polymorphism. 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.