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.
Learning Objectives
- 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++
Intended Audience
- Beginner coders, new to C++
- Developers looking to upskill by adding C++ to their CV
- College students and anyone studying C++
Prerequisites
To get the most out of this course, you should have a basic understanding of the fundamentals of C++.
In this section, we've worked quite a bit with inheritance and polymorphism. We've solidified and extended our understanding of Object-Oriented Programming and now you should have a reasonably solid grasp on encapsulation, inheritance, and polymorphism and be able to at least articulate what they are. This can help you when designing classes and systems while working on software engineering teams and also for job interviews. In this lecture, we will put some of your newfound skills to work. You should open the AnimalFun project that we worked on earlier and add an entirely new class. The Cat class. The Cat is very simple, it should inherit from the animal class. So, that means for the makeNoise and eat methods, you should provide a reasonable implementation. For example, makeNoise could return the string Meow and eat could return Tasty-kitty food. You'll notice Cat doesn't have any additional data and no private members, so you don't need a private section in your Cat class. You just need to implement the constructor and the chaseMouse method, which should directly print "I'm chasing a mouse!" to the console. Test to the Cat object using a polymorphic reference. As a hint, you'll need an animal pointer but a Cat object created dynamically. Do your test in main and don't forget to properly manage your memory too. As a big hint, you're going to have a little problem when you want to call chaseMouse from the animalPointer. Adding a chaseMouse to animal isn't a good solution. So, when you call this method, you need to explicitly cast the animalPointer to a catPointer in order to call that method. So, the syntax is provided for you on this slide. So, we cast the catPointer using a cat* in parentheses and then the whole thing is in parentheses. So, we have casted the catPointer which is an animalPointer to a catPointer, so it can call chaseMouse. Since animal doesn't have the chaseMouse method, you need to do this casting in order to call it. We didn't have to do this with things like makeNoise or eat because animal has those methods as does Cat and Dog. Alright. So, here's the Animalfun project that's been updated with the new derived Cat class and some testing for that class. So, 'Debug', 'Start Without Debugging' and that's what it looks like when the information is printed out. So, Cat noise?Meow!, Cat eating? Tasty kitty food! and I'm chasing a mouse! or something like that, that should be good. Hopefully this is a reasonable challenge for you. And you use proper syntax throughout. So, give this your best shot. Come back when you're done or if you need some help. How did the addition of that Cat derived class go? Let's work on this one together. So, of course we need to add a new header file Cat.h. Oops, see good thing we check before we hit enter, and cat.cpp to the source files. And we will of course update main after we get this created here. #ifndef CAT_ H, #define CAT_H, endif. We need to include string. We also in order to inherit from Animals, have to include Animal.h. Not int, sorry. class Cat : public Animal, just like dog does. Remember we do not have any private data or private methods, so we don't need a private section. Cat (string name, double weight). And we also have the chaseMouse, which is a new method, but we also have to provide implementations from makeNoise and also eat. There we go, now go over to Cat.cpp include Cat.h. And of course we will copy over these methods and give them bodies. All right. Now the class name and the scope resolution operator. There we go, so far so good. Now the constructor all we really need to do is pass on the data to the Animal constructor, right here. Give it a second and it should remove the error and it does. All right, now chaseMouse that's supposed to directly print to the console. So, in order to do this, I will put I'm chasing a mouse, there we go. Opps, doesn't know what cout is because we should include iostream. There we go, using namespace std; "I'm chasing a mouse". makeNoise should return a string because of the way it's used. And then eat should also return a string, I believe we said Tasty kitty food, because what that should be. And of course we probably want to do a little test in main. So, in addition to Dog, we will include Cat.h. I will create an animalPointer, so Animal* catPtr = new Cat ("Felix", 12); little lighter than our dogs. And now, I'm going to print out something like cout<<"Cat noise? "<< catPtr=> makeNoise() then cout<<"Cat eating"<< endl; Oops, probably want to actually do something, right? Getting a little ahead of myself here. There we go, not too bad. Sorry, there we go. And of course I want to call chaseMouse. Now if you try to do catPtr => chaseMouse(), you'll notice it doesn't show up on Intelli sense and it also underlines it, and says "Animal" has no member named "chaseMouse". That's accurate and that's true. And I said the solution to this is not to add a chaseMouse in order to get Animal to recognize it, you don't want to add that to the Animal class. That doesn't make any sense because every time you have a special behavior you have to edit to Animal that kind of defeats the purpose of having inheritance. But in this case, even though we're using a polymorphic reference, you could either cast it back and store it in a catPtr. Have a catPtr point to it or you can just on the fly as needed cast it to a catPtr and this is an older style cast. Now we also want to delete to the catPtr down at the bottom and just for good habits, set catPtr = nullptr. All right, let's run it. All right, looks pretty good. The cat's going meow. Tasty kitty food and then prints out I'm chasing a mouse; nice. So, it looks like our cat is now working just fine. So, the only disadvantage to using the Animal* was when we have to call something specifically implemented by cat that isn't declared inside Animal. We had to do a cast on the pointer to cast it back to a catPtr. And just to make sure you're aware there is actually another way to perform this cast. A lot of C++ developers prefer a newer syntax for pointer casting using something called reinterpret cast. Let's change it and retest to make sure that it still works. So, instead of this, which is the older style, we're going to do this. So, we're going to reinterpret_cast, and in angle braces, so these are the less than sign, greater than sign if you want to look at it that way, and then we have to put catPtr and you still do chaseMouse that way. So, instead of the little simple thing here with Cat* catPtr, we have reinterpret cast, you tell it what you're casting it to and then pass the pointer that you're casting from. So, this is considered a little bit safer and some people just prefer it. So, 'Debug' 'Start without debugging'. Oops, there's a build error. Next, oh, I see, forgot a semicolon; there we go. 'Debug' 'Start without debugging' and that's better. So, it's the same thing, I'm chasing a mouse. So, not really different behavior. Again, the syntax is pretty for both, so a lot of developers don't like it, but to be fair, it is a more modern approach and it is considered a safer way to change one type of pointer to another. In our case from an animalPtr to a catPtr, as specified in the angle brackets next to the reinterpret cast. So, I just wanted to make sure you saw this in case you see it somewhere else you won't be confused. In the next lecture, I have another project for you. You will work at another cool object oriented system where you will construct a role playing game, character creation program. Let's see what that's all about. 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.