‫So in this lecture, we're going to be talking all about the virtual method in C++.
‫We've seen it before, we've used it, but have we fully understood it?
‫Let's see.
‫So the idea of the virtual method is that it allows us to override functions in a base class.
‫We've seen this with things like begin, play and tic in Unreal, but let's get further into this and
‫understand why they're marked as virtual.
‫It allows us to change functionality in that base class, and it does something called Dynamic Dispatch,
‫which we're going to talk about in a second to kind of understand what this really means and why virtual
‫methods aren't the default functionality in C++ as they are in many other languages, such as C Sharp.
‫So let's have a look at this.
‫I'm going to be doing this in the CPP dot S-H website so that we're not in Unreal here at all.
‫We're just looking at the raw C++ functionality so that you can understand this language feature and
‫how it works.
‫Now, the first thing I'm going to do here is just go ahead and clear out the main method.
‫And in our use case, we're going to think about a class for guns, seeing as this is a very common
‫use case for games.
‫So let's have a look at a class called it gun fairly straightforwardly and then we're going to have
‫the body of this class be public and a void shoot method.
‫And I'm just going to go ahead and declare the body of this shoot method right here in line to keep
‫things super simple.
‫By the way, you can do this if you haven't seen this before, but generally speaking, we want to do
‫things in a separate C++ file to keep things separate, to make the compilation times quicker and so
‫on.
‫But here where it's just a toy example, this is fine, so we're going to do an STD C out.
‫So using C++ as output string stuff and we're going to go bang basically when we call this method and
‫then we're going to end line.
‫And that's their body of our shoot method.
‫And we can cap off the class with the curly brace and semicolon.
‫So let's go ahead and actually use this class.
‫I'm going to create a my gun variable in main and I am going to call my gun dot shoot and let's see
‫if everything is working here as it should.
‫Hit the run button and bang.
‫It is calling the method as we'd expect.
‫Now what happens if I want to extend my gun and perhaps make a rifle or pistol?
‫Let's call it a pistol.
‫So class pistol is a inherited from gun, which would do like this.
‫And if you haven't seen this before because you probably haven't written this necessarily before, you'd
‫do a public inheritance from guns so that other classes can see that you inherit from gun.
‫And then we do in the public section, we want to maybe create our own shoot method for the pistol that
‫overrides this functionality.
‫And instead of printing bang at the end here we want to print pill because it's a smaller gun, it makes
‫a smaller sound and that's our shoot method there.
‫And let's cap off the class there.
‫And what we want to do is create ourselves a pistol.
‫So pistol my pistol in the main method here.
‫And because these are just existing here, right on the main method, we're not using pointers to them.
‫That's why we're using the shot operator here instead of the arrow.
‫So the my pistol not shoot.
‫Let's see what that does.
‫I'll expect it to print PPU, which it does.
‫Cool.
‫Okay, so let's remove our methods that are calling.
‫Shoot directly on these and let's see how things would behave with a pointer.
‫So I'm going to create a gun pointer called Gun.
‫Peter.
‫And on the next line I could do it on the same line.
‫But for simplicity's sake, I'm going to do it on the next line.
‫I'm going to set that gun pointer to point to the address of that's the address of operator the address
‫of the my gun variable.
‫And then because this is a pointer, we need to use the arrow operator to call the shoot method.
‫So I'm going to call shoot on my gun, let's click run and we get bang as the result there.
‫Cool.
‫Now what happens if I do the same thing?
‫But instead of setting the gun pointer to point to my gun, I set it to point to my pistol.
‫Let's go ahead and hit run now.
‫Okay.
‫That's an interesting behavior there.
‫What's going on here is it is calling this first method in both instances.
‫So why hasn't this second shoot method been called?
‫We've got a pistol here as the pointer.
‫Well, what happens if you don't have a virtual method is that by default, C++ will use the type of
‫your pointer, which this is a gun pointer.
‫Remember, it will use that type to find the method to call.
‫So it will go and call this shoot method at the top rather than the overridden method in pistol.
‫In order for it to call the overridden and method in pistol, it would have to call it would have to
‫have a pointer of type pistol.
‫Now that's fine.
‫And you can see why they do this.
‫It's for efficiency.
‫C++ is all about efficiency.
‫If something is going to cost more when it's compiled, when it runs, then C++ won't do it by default
‫unless you ask it to.
‫So it's very easy for C++ to make the look up and go, Well, this is a gun pointer, so I'll call this
‫gun pointer method.
‫And this is where Dynamic Dispatch comes in.
‫This fancy term basically means that we don't want it to do that.
‫What we want it to do is say, Hang on a second, what's actually stored in that gun pointer?
‫What's the real type there?
‫And the real type we realize is it's a type pistol.
‫And so we've got to ask ourselves, is there a method for that type that's overridden?
‫And yes, there is.
‫So how do we give C++ the permission to be just that little bit less efficient and give us the ability
‫to override without having to change that pointer type, which isn't always necessarily possible.
‫In fact, in many cases this isn't possible, as is the case when you're having your own custom actor
‫class.
‫Unreal doesn't have the pointer set up to point to your particular act class that would require them
‫to change the whole engine every time you introduce a new class.
‫No, that's just not possible.
‫They have a pointer to something of type actor star.
‫So when they call begin play, you want it to call your begin play method.
‫So it has to be virtual.
‫And that is the key here.
‫If we stick virtual in front of the method in the parent class, this now signals to C++ that hang on
‫a second, if I am calling shoot on a pointer of type gun pointer, I need to check that this isn't,
‫for example, a pistol and that this shoot method has been overridden.
‫So if we go ahead and hit run now, you can see we get bang and then pill.
‫So it is working as we'd expect with Dynamic Dispatch.
‫And that is the term for this thing where we basically just mean check what kind of type this is really
‫being held in the pointer and call the relevant method.
‫Now there is an extra little bit of syntax that you will often see as use and that is the override keyword.
‫And you put that after a method that you are trying to override as virtual.
‫And basically the override keyword isn't strictly necessary, nor is putting virtual again against something
‫on the child class of a gun.
‫So you don't have to put virtual, but it doesn't hurt to do it.
‫But override is particularly helpful because it allows us to just make sure that we've got our naming
‫correct.
‫So if I hit run, everything runs as before when I have override.
‫But say I had mistakenly got the name of this method wrong so I don't do the override.
‫And I had called it a no shoot.
‫For example, I had copied the name wrong.
‫I typed it in instead of copying it.
‫If I hit run now, then you see, we've got the same error again because we're trying to call to shoot.
‫We mistakenly overrode it incorrectly.
‫It's going bang, bang.
‫So the way I could avoid this is by saying, Well, I'm trying to override something.
‫So I put my override keyword in here and if I try to compile it now, you can see that it's saying shooter
‫is marked as override, but there is no method, no virtual method for me to override, in which case
‫I can go, Oh yeah, I've mistyped that.
‫So I'm going to go ahead and correct my code and just make it back to shoot.
‫And now it works as I intended.
‫So it's just that little bit of extra safety by putting that override there and instantly this.
‫It also protects us against the case where the thing that we're trying to override isn't virtual.
‫If I try to do that, you can see that it's saying it's marked as override, but it doesn't override
‫because that parent class doesn't have a virtual function for shoot.
‫So hopefully this has given you somewhat of an overview of how C++ uses and implements virtual functions
‫and why we have to be so explicit about them.
‫Now let's think about some more use cases for virtual functions in general.
‫We've already seen some from the engine.
‫Where have you seen virtual used before?
‫Where can you imagine using it?
‫We've just seen a use case example where you might have a gun and different overrides of that that implement
‫shoot in different ways.
‫How else could you imagine using virtual functions that override the functionality in parent classes
‫when you thought of an answer to those two questions?
‫Go and follow the link to the discussions in this lecture and post your answer there.
‫The use cases and the places that you've used them before and see what other people have come up with.
‫Maybe that will help you solidify your understanding of virtual methods.
‫That's it for this lecture.
‫I'll see you in the next one where we'll be using virtual methods in anger.