﻿1
00:00:04,350 --> 00:00:09,720
‫So in this lecture, we're going to be talking all about the virtual method in C++.

2
00:00:09,720 --> 00:00:13,170
‫We've seen it before, we've used it, but have we fully understood it?

3
00:00:13,170 --> 00:00:14,100
‫Let's see.

4
00:00:14,100 --> 00:00:20,460
‫So the idea of the virtual method is that it allows us to override functions in a base class.

5
00:00:20,460 --> 00:00:27,210
‫We've seen this with things like begin, play and tic in Unreal, but let's get further into this and

6
00:00:27,210 --> 00:00:29,880
‫understand why they're marked as virtual.

7
00:00:29,880 --> 00:00:38,340
‫It allows us to change functionality in that base class, and it does something called Dynamic Dispatch,

8
00:00:38,340 --> 00:00:44,550
‫which we're going to talk about in a second to kind of understand what this really means and why virtual

9
00:00:44,550 --> 00:00:50,820
‫methods aren't the default functionality in C++ as they are in many other languages, such as C Sharp.

10
00:00:50,820 --> 00:00:52,320
‫So let's have a look at this.

11
00:00:52,440 --> 00:00:59,910
‫I'm going to be doing this in the CPP dot S-H website so that we're not in Unreal here at all.

12
00:00:59,910 --> 00:01:05,160
‫We're just looking at the raw C++ functionality so that you can understand this language feature and

13
00:01:05,160 --> 00:01:06,090
‫how it works.

14
00:01:06,150 --> 00:01:10,680
‫Now, the first thing I'm going to do here is just go ahead and clear out the main method.

15
00:01:10,680 --> 00:01:18,120
‫And in our use case, we're going to think about a class for guns, seeing as this is a very common

16
00:01:18,120 --> 00:01:19,680
‫use case for games.

17
00:01:19,680 --> 00:01:26,760
‫So let's have a look at a class called it gun fairly straightforwardly and then we're going to have

18
00:01:26,760 --> 00:01:31,860
‫the body of this class be public and a void shoot method.

19
00:01:32,520 --> 00:01:38,460
‫And I'm just going to go ahead and declare the body of this shoot method right here in line to keep

20
00:01:38,460 --> 00:01:39,310
‫things super simple.

21
00:01:39,330 --> 00:01:44,550
‫By the way, you can do this if you haven't seen this before, but generally speaking, we want to do

22
00:01:44,550 --> 00:01:49,470
‫things in a separate C++ file to keep things separate, to make the compilation times quicker and so

23
00:01:49,470 --> 00:01:49,770
‫on.

24
00:01:49,770 --> 00:01:55,290
‫But here where it's just a toy example, this is fine, so we're going to do an STD C out.

25
00:01:55,290 --> 00:02:03,390
‫So using C++ as output string stuff and we're going to go bang basically when we call this method and

26
00:02:03,390 --> 00:02:04,980
‫then we're going to end line.

27
00:02:05,570 --> 00:02:07,850
‫And that's their body of our shoot method.

28
00:02:07,850 --> 00:02:11,720
‫And we can cap off the class with the curly brace and semicolon.

29
00:02:11,960 --> 00:02:14,750
‫So let's go ahead and actually use this class.

30
00:02:14,750 --> 00:02:23,510
‫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

31
00:02:23,510 --> 00:02:25,910
‫if everything is working here as it should.

32
00:02:25,940 --> 00:02:28,070
‫Hit the run button and bang.

33
00:02:28,160 --> 00:02:30,530
‫It is calling the method as we'd expect.

34
00:02:30,980 --> 00:02:39,470
‫Now what happens if I want to extend my gun and perhaps make a rifle or pistol?

35
00:02:39,470 --> 00:02:40,420
‫Let's call it a pistol.

36
00:02:40,430 --> 00:02:47,180
‫So class pistol is a inherited from gun, which would do like this.

37
00:02:47,180 --> 00:02:51,530
‫And if you haven't seen this before because you probably haven't written this necessarily before, you'd

38
00:02:51,530 --> 00:02:56,330
‫do a public inheritance from guns so that other classes can see that you inherit from gun.

39
00:02:56,600 --> 00:03:04,280
‫And then we do in the public section, we want to maybe create our own shoot method for the pistol that

40
00:03:04,280 --> 00:03:05,540
‫overrides this functionality.

41
00:03:05,540 --> 00:03:13,220
‫And instead of printing bang at the end here we want to print pill because it's a smaller gun, it makes

42
00:03:13,220 --> 00:03:17,420
‫a smaller sound and that's our shoot method there.

43
00:03:17,420 --> 00:03:20,150
‫And let's cap off the class there.

44
00:03:20,360 --> 00:03:23,300
‫And what we want to do is create ourselves a pistol.

45
00:03:23,300 --> 00:03:28,010
‫So pistol my pistol in the main method here.

46
00:03:28,670 --> 00:03:34,010
‫And because these are just existing here, right on the main method, we're not using pointers to them.

47
00:03:34,010 --> 00:03:38,450
‫That's why we're using the shot operator here instead of the arrow.

48
00:03:38,750 --> 00:03:42,260
‫So the my pistol not shoot.

49
00:03:42,260 --> 00:03:43,460
‫Let's see what that does.

50
00:03:43,610 --> 00:03:47,280
‫I'll expect it to print PPU, which it does.

51
00:03:47,300 --> 00:03:47,930
‫Cool.

52
00:03:48,260 --> 00:03:51,530
‫Okay, so let's remove our methods that are calling.

53
00:03:51,530 --> 00:03:57,050
‫Shoot directly on these and let's see how things would behave with a pointer.

54
00:03:57,290 --> 00:04:01,880
‫So I'm going to create a gun pointer called Gun.

55
00:04:02,660 --> 00:04:03,640
‫Peter.

56
00:04:04,570 --> 00:04:06,910
‫And on the next line I could do it on the same line.

57
00:04:06,910 --> 00:04:08,890
‫But for simplicity's sake, I'm going to do it on the next line.

58
00:04:08,890 --> 00:04:15,790
‫I'm going to set that gun pointer to point to the address of that's the address of operator the address

59
00:04:15,790 --> 00:04:18,310
‫of the my gun variable.

60
00:04:18,580 --> 00:04:23,830
‫And then because this is a pointer, we need to use the arrow operator to call the shoot method.

61
00:04:23,830 --> 00:04:30,400
‫So I'm going to call shoot on my gun, let's click run and we get bang as the result there.

62
00:04:30,400 --> 00:04:31,120
‫Cool.

63
00:04:31,210 --> 00:04:34,450
‫Now what happens if I do the same thing?

64
00:04:34,450 --> 00:04:40,840
‫But instead of setting the gun pointer to point to my gun, I set it to point to my pistol.

65
00:04:40,990 --> 00:04:42,550
‫Let's go ahead and hit run now.

66
00:04:42,880 --> 00:04:43,240
‫Okay.

67
00:04:43,240 --> 00:04:45,190
‫That's an interesting behavior there.

68
00:04:45,190 --> 00:04:51,880
‫What's going on here is it is calling this first method in both instances.

69
00:04:51,880 --> 00:04:55,510
‫So why hasn't this second shoot method been called?

70
00:04:55,510 --> 00:04:58,030
‫We've got a pistol here as the pointer.

71
00:04:58,300 --> 00:05:05,500
‫Well, what happens if you don't have a virtual method is that by default, C++ will use the type of

72
00:05:05,500 --> 00:05:07,960
‫your pointer, which this is a gun pointer.

73
00:05:07,960 --> 00:05:11,890
‫Remember, it will use that type to find the method to call.

74
00:05:11,890 --> 00:05:18,130
‫So it will go and call this shoot method at the top rather than the overridden method in pistol.

75
00:05:18,130 --> 00:05:23,530
‫In order for it to call the overridden and method in pistol, it would have to call it would have to

76
00:05:23,530 --> 00:05:25,630
‫have a pointer of type pistol.

77
00:05:25,960 --> 00:05:27,520
‫Now that's fine.

78
00:05:27,520 --> 00:05:29,350
‫And you can see why they do this.

79
00:05:29,350 --> 00:05:30,430
‫It's for efficiency.

80
00:05:30,430 --> 00:05:32,410
‫C++ is all about efficiency.

81
00:05:32,410 --> 00:05:39,250
‫If something is going to cost more when it's compiled, when it runs, then C++ won't do it by default

82
00:05:39,250 --> 00:05:40,600
‫unless you ask it to.

83
00:05:40,630 --> 00:05:46,270
‫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

84
00:05:46,270 --> 00:05:47,620
‫gun pointer method.

85
00:05:47,620 --> 00:05:50,080
‫And this is where Dynamic Dispatch comes in.

86
00:05:50,080 --> 00:05:54,070
‫This fancy term basically means that we don't want it to do that.

87
00:05:54,070 --> 00:05:59,950
‫What we want it to do is say, Hang on a second, what's actually stored in that gun pointer?

88
00:05:59,950 --> 00:06:02,140
‫What's the real type there?

89
00:06:02,380 --> 00:06:06,250
‫And the real type we realize is it's a type pistol.

90
00:06:06,250 --> 00:06:12,520
‫And so we've got to ask ourselves, is there a method for that type that's overridden?

91
00:06:12,520 --> 00:06:13,600
‫And yes, there is.

92
00:06:13,600 --> 00:06:20,230
‫So how do we give C++ the permission to be just that little bit less efficient and give us the ability

93
00:06:20,230 --> 00:06:26,110
‫to override without having to change that pointer type, which isn't always necessarily possible.

94
00:06:26,110 --> 00:06:31,690
‫In fact, in many cases this isn't possible, as is the case when you're having your own custom actor

95
00:06:31,690 --> 00:06:32,470
‫class.

96
00:06:32,590 --> 00:06:38,290
‫Unreal doesn't have the pointer set up to point to your particular act class that would require them

97
00:06:38,290 --> 00:06:41,290
‫to change the whole engine every time you introduce a new class.

98
00:06:41,290 --> 00:06:43,120
‫No, that's just not possible.

99
00:06:43,120 --> 00:06:46,360
‫They have a pointer to something of type actor star.

100
00:06:46,360 --> 00:06:51,010
‫So when they call begin play, you want it to call your begin play method.

101
00:06:51,010 --> 00:06:52,630
‫So it has to be virtual.

102
00:06:52,630 --> 00:06:54,340
‫And that is the key here.

103
00:06:54,340 --> 00:07:02,500
‫If we stick virtual in front of the method in the parent class, this now signals to C++ that hang on

104
00:07:02,500 --> 00:07:10,120
‫a second, if I am calling shoot on a pointer of type gun pointer, I need to check that this isn't,

105
00:07:10,120 --> 00:07:14,350
‫for example, a pistol and that this shoot method has been overridden.

106
00:07:14,350 --> 00:07:19,390
‫So if we go ahead and hit run now, you can see we get bang and then pill.

107
00:07:19,420 --> 00:07:24,070
‫So it is working as we'd expect with Dynamic Dispatch.

108
00:07:24,070 --> 00:07:30,370
‫And that is the term for this thing where we basically just mean check what kind of type this is really

109
00:07:30,370 --> 00:07:33,430
‫being held in the pointer and call the relevant method.

110
00:07:33,940 --> 00:07:40,450
‫Now there is an extra little bit of syntax that you will often see as use and that is the override keyword.

111
00:07:40,450 --> 00:07:45,520
‫And you put that after a method that you are trying to override as virtual.

112
00:07:45,790 --> 00:07:53,680
‫And basically the override keyword isn't strictly necessary, nor is putting virtual again against something

113
00:07:53,680 --> 00:07:56,200
‫on the child class of a gun.

114
00:07:56,200 --> 00:07:59,350
‫So you don't have to put virtual, but it doesn't hurt to do it.

115
00:07:59,560 --> 00:08:06,550
‫But override is particularly helpful because it allows us to just make sure that we've got our naming

116
00:08:06,550 --> 00:08:07,030
‫correct.

117
00:08:07,030 --> 00:08:10,690
‫So if I hit run, everything runs as before when I have override.

118
00:08:10,690 --> 00:08:17,290
‫But say I had mistakenly got the name of this method wrong so I don't do the override.

119
00:08:17,290 --> 00:08:19,490
‫And I had called it a no shoot.

120
00:08:19,870 --> 00:08:22,750
‫For example, I had copied the name wrong.

121
00:08:22,750 --> 00:08:24,520
‫I typed it in instead of copying it.

122
00:08:24,520 --> 00:08:29,230
‫If I hit run now, then you see, we've got the same error again because we're trying to call to shoot.

123
00:08:29,230 --> 00:08:32,350
‫We mistakenly overrode it incorrectly.

124
00:08:32,350 --> 00:08:33,820
‫It's going bang, bang.

125
00:08:33,910 --> 00:08:37,840
‫So the way I could avoid this is by saying, Well, I'm trying to override something.

126
00:08:37,840 --> 00:08:44,170
‫So I put my override keyword in here and if I try to compile it now, you can see that it's saying shooter

127
00:08:44,170 --> 00:08:50,260
‫is marked as override, but there is no method, no virtual method for me to override, in which case

128
00:08:50,260 --> 00:08:52,360
‫I can go, Oh yeah, I've mistyped that.

129
00:08:52,360 --> 00:08:57,340
‫So I'm going to go ahead and correct my code and just make it back to shoot.

130
00:08:57,340 --> 00:08:59,320
‫And now it works as I intended.

131
00:08:59,320 --> 00:09:04,150
‫So it's just that little bit of extra safety by putting that override there and instantly this.

132
00:09:04,240 --> 00:09:09,170
‫It also protects us against the case where the thing that we're trying to override isn't virtual.

133
00:09:09,190 --> 00:09:14,680
‫If I try to do that, you can see that it's saying it's marked as override, but it doesn't override

134
00:09:14,680 --> 00:09:19,410
‫because that parent class doesn't have a virtual function for shoot.

135
00:09:19,420 --> 00:09:25,570
‫So hopefully this has given you somewhat of an overview of how C++ uses and implements virtual functions

136
00:09:25,570 --> 00:09:28,330
‫and why we have to be so explicit about them.

137
00:09:28,600 --> 00:09:32,890
‫Now let's think about some more use cases for virtual functions in general.

138
00:09:32,890 --> 00:09:34,750
‫We've already seen some from the engine.

139
00:09:34,750 --> 00:09:37,630
‫Where have you seen virtual used before?

140
00:09:38,450 --> 00:09:40,190
‫Where can you imagine using it?

141
00:09:40,220 --> 00:09:45,110
‫We've just seen a use case example where you might have a gun and different overrides of that that implement

142
00:09:45,110 --> 00:09:46,880
‫shoot in different ways.

143
00:09:47,300 --> 00:09:53,630
‫How else could you imagine using virtual functions that override the functionality in parent classes

144
00:09:53,630 --> 00:09:55,530
‫when you thought of an answer to those two questions?

145
00:09:55,550 --> 00:10:01,290
‫Go and follow the link to the discussions in this lecture and post your answer there.

146
00:10:01,310 --> 00:10:06,010
‫The use cases and the places that you've used them before and see what other people have come up with.

147
00:10:06,020 --> 00:10:11,250
‫Maybe that will help you solidify your understanding of virtual methods.

148
00:10:11,270 --> 00:10:12,280
‫That's it for this lecture.

149
00:10:12,290 --> 00:10:15,710
‫I'll see you in the next one where we'll be using virtual methods in anger.

