﻿1
00:00:04,440 --> 00:00:09,690
‫Dus in deze lezing gaan we het hebben over de virtuele methode in C++.

2
00:00:09,690 --> 00:00:13,110
‫We hebben het eerder gezien, we hebben het gebruikt, maar hebben we het volledig begrepen?

3
00:00:13,110 --> 00:00:13,860
‫Laat ons zien.

4
00:00:14,220 --> 00:00:20,400
‫Dus het idee van een virtuele methode is dat het ons in staat stelt om functies in een basisklasse te overschrijven.

5
00:00:20,400 --> 00:00:24,690
‫We hebben dit gezien met dingen als beginnen, spelen en opnemen in Unreal.

6
00:00:25,020 --> 00:00:29,640
‫Maar laten we hier verder op ingaan en begrijpen waarom ze als virtueel zijn gemarkeerd.

7
00:00:30,030 --> 00:00:38,130
‫Het stelt ons in staat om de functionaliteit in die basisklasse te veranderen, en het doet iets dat Dynamic Dispatch wordt genoemd, waar

8
00:00:38,430 --> 00:00:44,520
‫we het zo meteen over zullen hebben om te begrijpen wat dit echt betekent en waarom virtuele

9
00:00:44,520 --> 00:00:50,610
‫methoden niet de standaardfunctionaliteit zijn in C++ zoals ze zijn in veel andere talen, zoals C Sharp.

10
00:00:50,910 --> 00:00:52,050
‫Dus laten we hier eens naar kijken.

11
00:00:52,500 --> 00:00:59,850
‫Ik ga dit doen op de CPP dot S-H website zodat we hier helemaal niet in Unreal zijn.

12
00:00:59,850 --> 00:01:05,130
‫We kijken alleen naar de onbewerkte C++-functionaliteit, zodat u deze taalfunctie kunt begrijpen en hoe deze

13
00:01:05,130 --> 00:01:05,820
‫werkt.

14
00:01:06,300 --> 00:01:10,440
‫Nu, het eerste dat ik hier ga doen, is gewoon doorgaan en de hoofdmethode opruimen.

15
00:01:10,770 --> 00:01:18,390
‫En in onze use case gaan we nadenken over een klasse voor wapens, aangezien dit een veel voorkomende use case is

16
00:01:18,390 --> 00:01:19,380
‫voor games.

17
00:01:19,830 --> 00:01:26,700
‫Dus laten we een klasse bekijken, het geweer vrij eenvoudig koelen en dan zullen we het

18
00:01:26,700 --> 00:01:31,560
‫lichaam van deze klasse openbaar maken en een void shoot-methode.

19
00:01:32,550 --> 00:01:38,400
‫En ik ga gewoon door en verklaar de inhoud van deze schietmethode hier in de rij om de dingen supereenvoudig

20
00:01:38,400 --> 00:01:39,290
‫te houden.

21
00:01:39,300 --> 00:01:41,310
‫Trouwens, je kunt dit doen als je dit nog niet eerder hebt gezien.

22
00:01:41,520 --> 00:01:47,820
‫Maar over het algemeen willen we dingen in een apart C++-bestand doen om dingen gescheiden te houden, de compilatietijden

23
00:01:47,820 --> 00:01:49,560
‫sneller te maken enzovoort.

24
00:01:49,860 --> 00:01:52,140
‫Maar hier, waar het slechts een speelgoedvoorbeeld is, is dit prima.

25
00:01:52,650 --> 00:01:55,260
‫Dus we gaan een SD uitkijken.

26
00:01:55,260 --> 00:01:59,730
‫Dus C++ gebruiken als output string stuff en we gaan knallen.

27
00:02:00,360 --> 00:02:04,710
‫Kortom, wanneer we deze methode aanroepen en dan gaan we naar de eindregel.

28
00:02:05,630 --> 00:02:07,820
‫En dat is de kern van onze parachutemethode.

29
00:02:07,820 --> 00:02:11,510
‫En we kunnen de klas afsluiten met de accolade en de puntkomma.

30
00:02:12,050 --> 00:02:14,680
‫Dus laten we doorgaan en deze klasse daadwerkelijk gebruiken.

31
00:02:14,690 --> 00:02:23,420
‫Ik ga een my gun-variabele in het algemeen maken en ik ga mijn gun dot shoot noemen en laten we kijken of alles

32
00:02:23,420 --> 00:02:25,670
‫hier werkt zoals het hoort.

33
00:02:26,000 --> 00:02:27,830
‫Druk op de run-knop en knal.

34
00:02:28,210 --> 00:02:30,260
‫Het roept de methode aan zoals we zouden verwachten.

35
00:02:31,040 --> 00:02:40,220
‫Wat gebeurt er als ik mijn geweer wil verlengen en misschien een geweer of pistool wil maken dat een pistool wordt genoemd.

36
00:02:40,580 --> 00:02:46,970
‫Dus klasse pistool is een geërfd van pistool, dat zo zou doen.

37
00:02:47,180 --> 00:02:51,470
‫En als je dit nog niet eerder hebt gezien, omdat je dit waarschijnlijk niet eerder hebt

38
00:02:51,470 --> 00:02:56,090
‫geschreven, doe je een openbare erfenis van wapens zodat andere klassen kunnen zien dat je van wapen erft.

39
00:02:56,720 --> 00:03:04,220
‫En dan doen we in het openbare gedeelte, we willen misschien onze eigen schietmethode maken voor het pistool dat

40
00:03:04,220 --> 00:03:05,510
‫deze functionaliteit overschrijft.

41
00:03:05,510 --> 00:03:13,190
‫En in plaats van de knal aan het einde hier te printen, willen we pil printen omdat het een kleiner pistool is,

42
00:03:13,190 --> 00:03:17,270
‫het maakt een kleiner geluid en dat is onze schietmethode daar.

43
00:03:17,450 --> 00:03:19,910
‫En laten we de klas daar afsluiten.

44
00:03:20,510 --> 00:03:23,290
‫En wat we willen doen is een pistool voor onszelf maken.

45
00:03:23,300 --> 00:03:27,740
‫Dus schiet mijn pistool hier op de hoofdmethode.

46
00:03:28,640 --> 00:03:33,980
‫En omdat deze hier gewoon bestaan, precies op de hoofdmethode, gebruiken we geen verwijzingen naar hen.

47
00:03:33,980 --> 00:03:38,240
‫Daarom gebruiken we hier de puntoperator in plaats van de pijl.

48
00:03:38,840 --> 00:03:42,020
‫Dus de mijn pistool dot shoot.

49
00:03:42,200 --> 00:03:43,190
‫Laten we eens kijken wat dat doet.

50
00:03:43,670 --> 00:03:47,030
‫Ik verwacht dat het ppu zal printen, wat het ook doet.

51
00:03:47,320 --> 00:03:47,690
‫Stoer.

52
00:03:48,230 --> 00:03:51,470
‫Oké, dus laten we onze methoden die bellen verwijderen.

53
00:03:51,470 --> 00:03:56,810
‫Schiet er direct op en laten we eens kijken hoe de dingen zich zouden gedragen met een aanwijzer.

54
00:03:57,410 --> 00:04:01,580
‫Dus ik ga een pistoolwijzer maken met de naam pistool.

55
00:04:02,640 --> 00:04:03,420
‫Pieter.

56
00:04:04,600 --> 00:04:08,440
‫En op de volgende regel zou ik het op dezelfde regel kunnen doen, maar omwille van de eenvoud, ik ga het op de volgende

57
00:04:08,440 --> 00:04:08,860
‫regel doen.

58
00:04:08,860 --> 00:04:16,030
‫Ik ga die pistoolaanwijzer zo instellen dat deze wijst naar het adres van het adres van de operator, het

59
00:04:16,030 --> 00:04:18,070
‫adres van de my gun-variabele.

60
00:04:18,670 --> 00:04:23,710
‫En omdat het een aanwijzer is, moeten we de pijloperator gebruiken om de schietmethode aan te roepen.

61
00:04:23,830 --> 00:04:26,410
‫Dus ik ga schieten op mijn geweer roepen.

62
00:04:26,830 --> 00:04:30,310
‫Laten we op uitvoeren klikken en we krijgen knal als resultaat daar.

63
00:04:30,370 --> 00:04:30,850
‫Stoer.

64
00:04:31,330 --> 00:04:34,420
‫Wat gebeurt er als ik hetzelfde doe?

65
00:04:34,420 --> 00:04:40,570
‫Maar in plaats van het pistool op mijn pistool te richten, zette ik het op mijn pistool.

66
00:04:40,960 --> 00:04:42,280
‫Laten we doorgaan en nu rennen.

67
00:04:42,850 --> 00:04:43,200
‫Oké.

68
00:04:43,210 --> 00:04:44,950
‫Dat is een interessant gedrag daar.

69
00:04:45,340 --> 00:04:51,610
‫Wat hier aan de hand is, is dat deze eerste methode in beide gevallen wordt aangeroepen.

70
00:04:52,000 --> 00:04:55,450
‫Dus waarom is deze tweede shoot-methode niet genoemd?

71
00:04:55,450 --> 00:04:57,790
‫We hebben hier een pistool als aanwijzer.

72
00:04:58,390 --> 00:05:05,440
‫Welnu, wat er gebeurt als je geen virtuele methode hebt, is dat C++ standaard het type van je

73
00:05:05,440 --> 00:05:07,900
‫aanwijzer gebruikt, wat een pistoolwijzer is.

74
00:05:07,900 --> 00:05:11,820
‫Onthoud dat het dat type zal gebruiken om de methode te vinden die moet worden aangeroepen.

75
00:05:11,830 --> 00:05:17,920
‫Dus het zal deze schietmethode bovenaan gaan noemen in plaats van de overschreven methode in het pistool.

76
00:05:18,190 --> 00:05:22,780
‫Om de overschreven methode in het pistool aan te roepen, zou het moeten bellen.

77
00:05:22,780 --> 00:05:25,390
‫Het zou een wijzer van het type pistool moeten hebben.

78
00:05:26,020 --> 00:05:27,490
‫Dat is prima.

79
00:05:27,490 --> 00:05:29,320
‫En je kunt zien waarom ze dit doen.

80
00:05:29,320 --> 00:05:30,370
‫Het is voor efficiëntie.

81
00:05:30,370 --> 00:05:32,200
‫Bij C++ draait alles om efficiëntie.

82
00:05:32,500 --> 00:05:39,220
‫Als iets meer gaat kosten wanneer het wordt gecompileerd, wanneer het wordt uitgevoerd, dan zal C++ het standaard niet doen, tenzij

83
00:05:39,220 --> 00:05:40,420
‫je erom vraagt.

84
00:05:40,750 --> 00:05:46,240
‫Dus het is heel gemakkelijk voor C++ om het op te zoeken en te gaan. Wel, dit is een pistoolwijzer, dus

85
00:05:46,240 --> 00:05:47,320
‫ik noem deze pistoolwijzermethode.

86
00:05:47,740 --> 00:05:50,040
‫En dit is waar Dynamic Dispatch om de hoek komt kijken.

87
00:05:50,050 --> 00:05:53,890
‫Deze mooie term betekent in feite dat we niet willen dat het dat doet.

88
00:05:54,160 --> 00:05:59,910
‫Wat we willen dat het doet, is zeggen, wacht even, wat is er eigenlijk opgeslagen in die pistoolwijzer?

89
00:05:59,920 --> 00:06:01,960
‫Wat is daar het echte type?

90
00:06:02,410 --> 00:06:06,040
‫En het echte type dat we ons realiseren is dat het een type pistool is.

91
00:06:06,310 --> 00:06:12,490
‫En dus moeten we ons afvragen, is er een methode voor dat type die overschreven wordt?

92
00:06:12,490 --> 00:06:13,570
‫En ja, die is er.

93
00:06:13,600 --> 00:06:20,080
‫Dus hoe geven we C++ de toestemming om net dat beetje minder efficiënt te zijn en geven we ons de

94
00:06:20,290 --> 00:06:26,050
‫mogelijkheid om te overschrijven zonder dat aanwijzertype te hoeven veranderen, wat niet altijd per se mogelijk is.

95
00:06:26,050 --> 00:06:31,660
‫In veel gevallen is het zelfs niet mogelijk, zoals het geval is wanneer je je eigen aangepaste actieve klasse

96
00:06:31,660 --> 00:06:32,170
‫hebt.

97
00:06:32,650 --> 00:06:38,350
‫Unreal heeft de aanwijzer niet ingesteld om naar uw specifieke klasse te verwijzen, waardoor ze de hele engine moeten

98
00:06:38,350 --> 00:06:41,110
‫veranderen telkens wanneer u een nieuwe klasse introduceert.

99
00:06:41,350 --> 00:06:42,910
‫Nee, dat kan gewoon niet.

100
00:06:43,210 --> 00:06:46,210
‫Ze hebben een verwijzing naar iets van het type act om in de hoofdrol te spelen.

101
00:06:46,450 --> 00:06:50,950
‫Dus toen ze begin play aanroepen, wilde je je Begin Play-methode aanroepen.

102
00:06:50,950 --> 00:06:52,450
‫Het moet dus virtueel zijn.

103
00:06:52,690 --> 00:06:54,160
‫En dat is de sleutel hier.

104
00:06:54,400 --> 00:07:02,440
‫Als we virtueel voor de methode in de bovenliggende klasse blijven, geeft dit nu een signaal aan C ++ dat een seconde blijft

105
00:07:02,440 --> 00:07:09,970
‫hangen, als ik shoot op een aanwijzer van het type gun pointer aanroep, moet ik controleren of dit bijvoorbeeld niet het geval

106
00:07:10,150 --> 00:07:14,080
‫is , een pistool en dat deze schietmethode is opgeheven.

107
00:07:14,500 --> 00:07:19,180
‫Dus als we doorgaan en nu rennen, kun je zien dat we knallen en dan pue.

108
00:07:19,570 --> 00:07:23,800
‫Dus het werkt zoals we zouden verwachten met dynamische verzending.

109
00:07:24,100 --> 00:07:30,340
‫En dat is de term voor dit ding, waar we eigenlijk gewoon bedoelen, controleren wat voor soort type dit echt in

110
00:07:30,340 --> 00:07:33,160
‫de aanwijzer wordt vastgehouden en de relevante methode aanroepen.

111
00:07:34,030 --> 00:07:39,670
‫Nu is er een extra klein beetje syntaxis dat u ons vaak zult zien gebruiken, en dat is

112
00:07:39,670 --> 00:07:40,420
‫het override-sleutelwoord.

113
00:07:40,420 --> 00:07:45,280
‫En dat zet je achter een methode die je probeert te overschrijven als virtueel.

114
00:07:45,910 --> 00:07:53,590
‫En eigenlijk is het override-sleutelwoord niet strikt noodzakelijk, en evenmin is virtueel opnieuw plaatsen tegen iets in

115
00:07:53,590 --> 00:07:56,160
‫de kinderklasse van een pistool.

116
00:07:56,170 --> 00:07:59,140
‫Je hoeft dus niet virtueel te zetten, maar het kan geen kwaad om het te doen.

117
00:07:59,650 --> 00:08:06,490
‫Maar overschrijven is vooral handig omdat het ons in staat stelt om ervoor te zorgen dat onze naam correct

118
00:08:06,490 --> 00:08:07,000
‫is.

119
00:08:07,000 --> 00:08:10,480
‫Dus als ik op uitvoeren druk, loopt alles zoals voorheen wanneer ik override heb.

120
00:08:10,810 --> 00:08:17,230
‫Maar stel dat ik per ongeluk de naam van deze methode verkeerd had, dus ik doe de override niet.

121
00:08:17,230 --> 00:08:20,680
‫En ik had het bijvoorbeeld een note shooter genoemd.

122
00:08:20,950 --> 00:08:22,720
‫Ik heb de naam verkeerd gekopieerd.

123
00:08:22,720 --> 00:08:24,280
‫Ik typte het in in plaats van het te kopiëren.

124
00:08:24,610 --> 00:08:28,960
‫Als ik nu op rennen druk, zie je, we hebben weer dezelfde fout omdat we proberen af te koelen om te schieten.

125
00:08:29,320 --> 00:08:32,170
‫We hebben het per abuis ten onrechte overschreven.

126
00:08:32,410 --> 00:08:33,550
‫Het gaat knal, knal.

127
00:08:34,060 --> 00:08:37,780
‫Dus de manier waarop ik dit kan vermijden is door te zeggen: Nou, ik probeer iets te negeren.

128
00:08:37,780 --> 00:08:43,750
‫Dus ik heb mijn override-sleutelwoord hier geplaatst, en als ik het nu probeer te compileren, kun je zien dat er staat dat

129
00:08:43,750 --> 00:08:49,510
‫shooter is gemarkeerd als override, maar er is geen methode, geen virtuele methode die ik kan overschrijven, in welk geval ik

130
00:08:49,510 --> 00:08:52,360
‫kan gaan , Oh ja, dat heb ik verkeerd getypt.

131
00:08:52,360 --> 00:08:57,070
‫Dus ik ga door en corrigeer mijn code en ga gewoon terug om te schieten.

132
00:08:57,460 --> 00:08:59,290
‫En nu werkt het zoals ik het bedoeld had.

133
00:08:59,290 --> 00:09:04,130
‫Het is dus net dat beetje extra veiligheid door die override daar te plaatsen en meteen dit.

134
00:09:04,180 --> 00:09:09,130
‫Zou ons ook beschermen tegen het geval dat het ding dat we proberen te negeren niet virtueel is.

135
00:09:09,130 --> 00:09:14,620
‫Als ik dat probeer te doen, kun je zien dat het zegt dat het is gemarkeerd als overschrijven,

136
00:09:14,620 --> 00:09:19,210
‫maar het overschrijft niet omdat die bovenliggende klasse geen virtuele functie voor schieten heeft.

137
00:09:19,390 --> 00:09:25,540
‫Dus hopelijk geeft dit je een beetje een overzicht van hoe C++ virtuele functies gebruikt en implementeert en waarom

138
00:09:25,540 --> 00:09:28,090
‫we er zo expliciet over moeten zijn.

139
00:09:28,690 --> 00:09:32,860
‫Laten we nu eens nadenken over wat meer gebruiksscenario's voor virtuele functies in het algemeen.

140
00:09:32,860 --> 00:09:34,690
‫We hebben al wat van de motor gezien.

141
00:09:34,690 --> 00:09:37,360
‫Waar heb je virtual gebruikt eerder gezien?

142
00:09:38,510 --> 00:09:40,150
‫Waar kun je je voorstellen dat je het gebruikt?

143
00:09:40,160 --> 00:09:45,050
‫We hebben zojuist een use case-voorbeeld gezien waarbij je een pistool en verschillende overrides daarvan hebt

144
00:09:45,050 --> 00:09:46,640
‫die op verschillende manieren schieten.

145
00:09:47,390 --> 00:09:53,600
‫Hoe kun je je anders voorstellen dat je virtuele functies gebruikt om de functionaliteit in bovenliggende klassen te overschrijven?

146
00:09:53,600 --> 00:09:58,190
‫Als je een antwoord op die twee vragen hebt bedacht, volg dan de link naar de

147
00:09:58,190 --> 00:10:00,890
‫discussies in deze lezing en post je antwoord.

148
00:10:00,890 --> 00:10:05,810
‫Ze de use-cases en de plaatsen waar je ze eerder hebt gebruikt en zien wat andere mensen hebben bedacht.

149
00:10:06,080 --> 00:10:11,150
‫Misschien helpt dat je om je begrip van virtuele methoden te verstevigen.

150
00:10:11,240 --> 00:10:12,230
‫Dat was het voor deze lezing.

151
00:10:12,230 --> 00:10:15,500
‫Ik zie je in de volgende waar we in woede virtuele methoden zullen gebruiken.

