﻿1
00:00:04,440 --> 00:00:09,690
‫Quindi in questa lezione parleremo del metodo virtuale in C++.

2
00:00:09,690 --> 00:00:13,110
‫L'abbiamo già visto, l'abbiamo usato, ma l'abbiamo capito fino in fondo?

3
00:00:13,110 --> 00:00:13,860
‫Lasciaci vedere.

4
00:00:14,220 --> 00:00:20,400
‫Quindi l'idea di un metodo virtuale è che ci permette di sovrascrivere le funzioni in una classe base.

5
00:00:20,400 --> 00:00:24,690
‫L'abbiamo visto con cose come Begin, Play e Take in Unreal.

6
00:00:25,020 --> 00:00:29,640
‫Ma andiamo oltre e comprendiamo perché sono contrassegnati come virtuali.

7
00:00:30,030 --> 00:00:38,130
‫Ci consente di modificare la funzionalità in quella classe base e fa qualcosa chiamato Dynamic Dispatch, di cui parleremo tra

8
00:00:38,430 --> 00:00:44,520
‫un secondo per capire cosa significa veramente e perché i metodi virtuali non sono la

9
00:00:44,520 --> 00:00:50,610
‫funzionalità predefinita in C++ come lo sono in molte altre lingue, come C Sharp.

10
00:00:50,910 --> 00:00:52,050
‫Quindi diamo un'occhiata a questo.

11
00:00:52,500 --> 00:00:59,850
‫Lo farò nel sito Web CPP dot SH in modo che non siamo affatto in Unreal qui.

12
00:00:59,850 --> 00:01:05,130
‫Stiamo solo esaminando la funzionalità C++ grezza in modo che tu possa capire questa funzionalità del linguaggio e

13
00:01:05,130 --> 00:01:05,820
‫come funziona.

14
00:01:06,300 --> 00:01:10,440
‫Ora, la prima cosa che farò qui è semplicemente andare avanti e chiarire il metodo principale.

15
00:01:10,770 --> 00:01:18,390
‫E nel nostro caso d'uso penseremo a una classe per le armi, visto che questo è un caso d'uso molto comune per

16
00:01:18,390 --> 00:01:19,380
‫i giochi.

17
00:01:19,830 --> 00:01:26,700
‫Quindi diamo un'occhiata a una classe, raffreddiamo la pistola in modo abbastanza diretto e quindi faremo in modo che

18
00:01:26,700 --> 00:01:31,560
‫il corpo di questa classe sia pubblico e un metodo di tiro vuoto.

19
00:01:32,550 --> 00:01:38,400
‫E ho intenzione di andare avanti e dichiarare il corpo di questo metodo di ripresa proprio qui in linea per mantenere le

20
00:01:38,400 --> 00:01:39,290
‫cose super semplici.

21
00:01:39,300 --> 00:01:41,310
‫A proposito, puoi farlo se non l'hai mai visto prima.

22
00:01:41,520 --> 00:01:47,820
‫Ma in generale, vogliamo fare le cose in un file C++ separato per mantenere le cose separate, per rendere i tempi di

23
00:01:47,820 --> 00:01:49,560
‫compilazione più rapidi e così via.

24
00:01:49,860 --> 00:01:52,140
‫Ma qui, dove è solo un esempio di giocattolo, va bene.

25
00:01:52,650 --> 00:01:55,260
‫Quindi faremo una prova SD.

26
00:01:55,260 --> 00:01:59,730
‫Quindi usando C++ come roba di stringa di output e andremo a fare il botto.

27
00:02:00,360 --> 00:02:04,710
‫Fondamentalmente quando chiamiamo questo metodo e poi andremo a fine riga.

28
00:02:05,630 --> 00:02:07,820
‫E questo è il corpo del nostro metodo dello scivolo.

29
00:02:07,820 --> 00:02:11,510
‫E possiamo chiudere la classe in cui la parentesi graffa e il punto e virgola.

30
00:02:12,050 --> 00:02:14,680
‫Quindi andiamo avanti e usiamo effettivamente questa classe.

31
00:02:14,690 --> 00:02:23,420
‫Creerò una variabile my gun in main e chiamerò il mio gun dot shoot e vediamo se tutto

32
00:02:23,420 --> 00:02:25,670
‫funziona qui come dovrebbe.

33
00:02:26,000 --> 00:02:27,830
‫Premi il pulsante Esegui e sbatti.

34
00:02:28,210 --> 00:02:30,260
‫Sta chiamando il metodo come ci aspetteremmo.

35
00:02:31,040 --> 00:02:40,220
‫Ora cosa succede se voglio estendere la mia pistola e forse fare un fucile o una pistola che si chiama pistola.

36
00:02:40,580 --> 00:02:46,970
‫Quindi la pistola di classe è ereditata dalla pistola, il che farebbe così.

37
00:02:47,180 --> 00:02:51,470
‫E se non l'avevi visto prima perché probabilmente non l'hai scritto necessariamente prima, fai

38
00:02:51,470 --> 00:02:56,090
‫un'eredità pubblica dalle armi in modo che le altre classi possano vedere che erediti dalle armi.

39
00:02:56,720 --> 00:03:04,220
‫E poi, nella sezione pubblica, vogliamo forse creare il nostro metodo di tiro per la pistola che prevale

40
00:03:04,220 --> 00:03:05,510
‫su questa funzionalità.

41
00:03:05,510 --> 00:03:13,190
‫E invece di stampare il botto alla fine qui vogliamo stampare la pillola perché è una pistola più piccola, fa un suono

42
00:03:13,190 --> 00:03:17,270
‫più piccolo e questo è il nostro metodo di tiro lì.

43
00:03:17,450 --> 00:03:19,910
‫E chiudiamo la classe lì.

44
00:03:20,510 --> 00:03:23,290
‫E quello che vogliamo fare è creare noi stessi una pistola.

45
00:03:23,300 --> 00:03:27,740
‫Quindi pistola la mia pistola nel metodo principale qui.

46
00:03:28,640 --> 00:03:33,980
‫E poiché questi esistono solo qui, proprio sul metodo principale, non stiamo usando i puntatori ad essi.

47
00:03:33,980 --> 00:03:38,240
‫Ecco perché qui stiamo usando l'operatore punto invece della freccia.

48
00:03:38,840 --> 00:03:42,020
‫Quindi il mio tiro con la pistola.

49
00:03:42,200 --> 00:03:43,190
‫Vediamo cosa fa.

50
00:03:43,670 --> 00:03:47,030
‫Mi aspetto che stampi ppu, cosa che fa.

51
00:03:47,320 --> 00:03:47,690
‫Freddo.

52
00:03:48,230 --> 00:03:51,470
‫Ok, quindi rimuoviamo i nostri metodi che stanno chiamando.

53
00:03:51,470 --> 00:03:56,810
‫Sparate direttamente su questi e vediamo come si comporterebbero le cose con un puntatore.

54
00:03:57,410 --> 00:04:01,580
‫Quindi creerò un puntatore pistola chiamato gun.

55
00:04:02,640 --> 00:04:03,420
‫Peter.

56
00:04:04,600 --> 00:04:08,440
‫E nella riga successiva potrei farlo sulla stessa riga, ma per semplicità, lo farò nella riga

57
00:04:08,440 --> 00:04:08,860
‫successiva.

58
00:04:08,860 --> 00:04:16,030
‫Imposterò il puntatore della pistola in modo che punti all'indirizzo dell'indirizzo dell'operatore, l'indirizzo della

59
00:04:16,030 --> 00:04:18,070
‫variabile my gun.

60
00:04:18,670 --> 00:04:23,710
‫E poi, poiché è un puntatore, dobbiamo usare l'operatore freccia per chiamare il metodo di tiro.

61
00:04:23,830 --> 00:04:26,410
‫Quindi chiamerò sparare sulla mia pistola.

62
00:04:26,830 --> 00:04:30,310
‫Facciamo clic su Esegui e otteniamo il botto come risultato lì.

63
00:04:30,370 --> 00:04:30,850
‫Freddo.

64
00:04:31,330 --> 00:04:34,420
‫Ora cosa succede se faccio la stessa cosa?

65
00:04:34,420 --> 00:04:40,570
‫Ma invece di impostare la pistola puntata verso la mia pistola, l'ho impostata in modo che punti verso la mia pistola.

66
00:04:40,960 --> 00:04:42,280
‫Andiamo avanti e premiamo corri ora.

67
00:04:42,850 --> 00:04:43,200
‫Bene.

68
00:04:43,210 --> 00:04:44,950
‫È un comportamento interessante lì.

69
00:04:45,340 --> 00:04:51,610
‫Quello che sta succedendo qui è chiamare questo primo metodo in entrambi i casi.

70
00:04:52,000 --> 00:04:55,450
‫Allora perché questo secondo metodo di ripresa non è stato chiamato?

71
00:04:55,450 --> 00:04:57,790
‫Abbiamo una pistola qui come puntatore.

72
00:04:58,390 --> 00:05:05,440
‫Bene, quello che succede se non hai un metodo virtuale è che per impostazione predefinita, C++ utilizzerà il tipo del tuo

73
00:05:05,440 --> 00:05:07,900
‫puntatore, che è un puntatore di pistola.

74
00:05:07,900 --> 00:05:11,820
‫Ricorda, utilizzerà quel tipo per trovare il metodo da chiamare.

75
00:05:11,830 --> 00:05:17,920
‫Quindi andrà a chiamare questo metodo di tiro in alto piuttosto che il metodo sovrascritto nella pistola.

76
00:05:18,190 --> 00:05:22,780
‫Affinché possa chiamare il metodo sovrascritto in pistola, dovrebbe chiamare.

77
00:05:22,780 --> 00:05:25,390
‫Dovrebbe avere un puntatore di tipo pistola.

78
00:05:26,020 --> 00:05:27,490
‫Ora va bene.

79
00:05:27,490 --> 00:05:29,320
‫E puoi capire perché lo fanno.

80
00:05:29,320 --> 00:05:30,370
‫È per l'efficienza.

81
00:05:30,370 --> 00:05:32,200
‫C++ è tutto incentrato sull'efficienza.

82
00:05:32,500 --> 00:05:39,220
‫Se qualcosa costerà di più quando viene compilato, quando viene eseguito, C++ non lo farà per impostazione predefinita a meno che tu

83
00:05:39,220 --> 00:05:40,420
‫non lo richieda.

84
00:05:40,750 --> 00:05:46,240
‫Quindi è molto facile per C++ cercare e dire, Bene, questo è un puntatore della pistola, quindi chiamerò questo metodo del

85
00:05:46,240 --> 00:05:47,320
‫puntatore della pistola.

86
00:05:47,740 --> 00:05:50,040
‫Ed è qui che entra in gioco Dynamic Dispatch.

87
00:05:50,050 --> 00:05:53,890
‫Questo termine di fantasia fondamentalmente significa che non vogliamo che lo faccia.

88
00:05:54,160 --> 00:05:59,910
‫Quello che vogliamo che faccia è dire, aspetta un secondo, cosa è effettivamente memorizzato in quel puntatore di pistola?

89
00:05:59,920 --> 00:06:01,960
‫Qual è il vero tipo lì?

90
00:06:02,410 --> 00:06:06,040
‫E il vero tipo di cui ci rendiamo conto è che è un tipo di pistola.

91
00:06:06,310 --> 00:06:12,490
‫E quindi dobbiamo chiederci, c'è un metodo per quel tipo che è sovrascritto?

92
00:06:12,490 --> 00:06:13,570
‫E sì, c'è.

93
00:06:13,600 --> 00:06:20,080
‫Quindi, come diamo a C++ il permesso di essere solo un po' meno efficiente e ci diamo la possibilità di

94
00:06:20,290 --> 00:06:26,050
‫eseguire l'override senza dover modificare quel tipo di puntatore, il che non è sempre necessariamente possibile.

95
00:06:26,050 --> 00:06:31,660
‫In effetti, in molti casi non è possibile, come nel caso di una classe attiva

96
00:06:31,660 --> 00:06:32,170
‫personalizzata.

97
00:06:32,650 --> 00:06:38,350
‫Unreal non ha il puntatore impostato per puntare alla tua classe particolare che richiederebbe loro di cambiare l'intero

98
00:06:38,350 --> 00:06:41,110
‫motore ogni volta che introduci una nuova classe.

99
00:06:41,350 --> 00:06:42,910
‫No, non è possibile.

100
00:06:43,210 --> 00:06:46,210
‫Hanno un puntatore a qualcosa di tipo atto da recitare.

101
00:06:46,450 --> 00:06:50,950
‫Quindi, quando chiamano Begin Play, volevi chiamare il tuo metodo Begin Play.

102
00:06:50,950 --> 00:06:52,450
‫Quindi deve essere virtuale.

103
00:06:52,690 --> 00:06:54,160
‫E questa è la chiave qui.

104
00:06:54,400 --> 00:07:02,440
‫Se rimaniamo virtual davanti al metodo nella classe genitore, questo ora segnala a C++ che si blocca per un secondo, se sto

105
00:07:02,440 --> 00:07:09,970
‫chiamando shoot su un puntatore di tipo gun pointer, devo verificare che non lo sia, ad esempio , una pistola

106
00:07:10,150 --> 00:07:14,080
‫e che questo metodo di tiro è stato ignorato.

107
00:07:14,500 --> 00:07:19,180
‫Quindi, se andiamo avanti e premiamo corri ora, puoi vedere che prendiamo il botto e poi il pue.

108
00:07:19,570 --> 00:07:23,800
‫Quindi funziona come ci aspetteremmo con l'invio dinamico.

109
00:07:24,100 --> 00:07:30,340
‫E questo è il termine per questa cosa in cui fondamentalmente intendiamo solo controllare che tipo di tipo è effettivamente

110
00:07:30,340 --> 00:07:33,160
‫contenuto nel puntatore e chiamare il metodo pertinente.

111
00:07:34,030 --> 00:07:39,670
‫Ora c'è un po' di sintassi in più che ci vedrai usare spesso, e questa è la parola

112
00:07:39,670 --> 00:07:40,420
‫chiave override.

113
00:07:40,420 --> 00:07:45,280
‫E lo metti dopo un metodo che stai cercando di ignorare come virtuale.

114
00:07:45,910 --> 00:07:53,590
‫E fondamentalmente la parola chiave override non è strettamente necessaria, né lo è mettere di nuovo virtuale contro qualcosa

115
00:07:53,590 --> 00:07:56,160
‫nella classe figlia di una pistola.

116
00:07:56,170 --> 00:07:59,140
‫Quindi non devi mettere virtuale, ma non fa male farlo.

117
00:07:59,650 --> 00:08:06,490
‫Ma l'override è particolarmente utile perché ci consente di assicurarci di avere la nostra denominazione

118
00:08:06,490 --> 00:08:07,000
‫corretta.

119
00:08:07,000 --> 00:08:10,480
‫Quindi, se premo Esegui, tutto funziona come prima quando ho l'override.

120
00:08:10,810 --> 00:08:17,230
‫Ma supponiamo di aver erroneamente sbagliato il nome di questo metodo, quindi non eseguo l'override.

121
00:08:17,230 --> 00:08:20,680
‫E l'avevo chiamato uno sparatutto, per esempio.

122
00:08:20,950 --> 00:08:22,720
‫Ho sbagliato a copiare il nome.

123
00:08:22,720 --> 00:08:24,280
‫L'ho digitato invece di copiarlo.

124
00:08:24,610 --> 00:08:28,960
‫Se premo Esegui ora, vedi, abbiamo di nuovo lo stesso errore perché stiamo cercando di raffreddare per sparare.

125
00:08:29,320 --> 00:08:32,170
‫Lo abbiamo erroneamente sovrascritto in modo errato.

126
00:08:32,410 --> 00:08:33,550
‫Sta andando botto, botto.

127
00:08:34,060 --> 00:08:37,780
‫Quindi il modo in cui potrei evitarlo è dicendo: Bene, sto cercando di ignorare qualcosa.

128
00:08:37,780 --> 00:08:43,750
‫Quindi ho inserito la mia parola chiave di override qui, e se provo a compilarla ora, puoi vedere che sta dicendo

129
00:08:43,750 --> 00:08:49,510
‫che lo sparatutto è contrassegnato come override, ma non c'è nessun metodo, nessun metodo virtuale per me da sovrascrivere, nel qual

130
00:08:49,510 --> 00:08:52,360
‫caso posso andare , Oh sì, l'ho digitato male.

131
00:08:52,360 --> 00:08:57,070
‫Quindi andrò avanti e correggerò il mio codice e lo farò tornare per sparare.

132
00:08:57,460 --> 00:08:59,290
‫E ora funziona come previsto.

133
00:08:59,290 --> 00:09:04,130
‫Quindi è solo un po' di sicurezza in più inserendo quell'override lì e istantaneamente questo.

134
00:09:04,180 --> 00:09:09,130
‫Ci proteggerebbe anche dal caso in cui la cosa che stiamo cercando di ignorare non è virtuale.

135
00:09:09,130 --> 00:09:14,620
‫Se provo a farlo, puoi vedere che sta dicendo che è contrassegnato come override, ma non

136
00:09:14,620 --> 00:09:19,210
‫sovrascrive perché quella classe genitore non ha una funzione virtuale per le riprese.

137
00:09:19,390 --> 00:09:25,540
‫Quindi si spera che questo ti stia dando una panoramica di come C++ usa e implementa le funzioni virtuali e

138
00:09:25,540 --> 00:09:28,090
‫perché dobbiamo essere così espliciti su di esse.

139
00:09:28,690 --> 00:09:32,860
‫Ora, pensiamo ad altri casi d'uso per le funzioni virtuali in generale.

140
00:09:32,860 --> 00:09:34,690
‫Ne abbiamo già visti alcuni dal motore.

141
00:09:34,690 --> 00:09:37,360
‫Dove hai mai visto il virtuale usato prima?

142
00:09:38,510 --> 00:09:40,150
‫Dove puoi immaginare di usarlo?

143
00:09:40,160 --> 00:09:45,050
‫Abbiamo appena visto un esempio di caso d'uso in cui potresti avere una pistola e diverse sostituzioni di quella che

144
00:09:45,050 --> 00:09:46,640
‫implementano le riprese in modi diversi.

145
00:09:47,390 --> 00:09:53,600
‫In quale altro modo potresti immaginare di utilizzare funzioni virtuali per sovrascrivere la funzionalità nelle classi padre?

146
00:09:53,600 --> 00:09:58,190
‫Quando hai pensato a una risposta a queste due domande, vai e segui il link alle

147
00:09:58,190 --> 00:10:00,890
‫discussioni in questa lezione e pubblica la tua risposta.

148
00:10:00,890 --> 00:10:05,810
‫Visualizzano i casi d'uso e i luoghi in cui li hai usati prima e vedono cosa hanno inventato altre persone.

149
00:10:06,080 --> 00:10:11,150
‫Forse questo ti aiuterà a consolidare la tua comprensione dei metodi virtuali.

150
00:10:11,240 --> 00:10:12,230
‫Questo è tutto per questa lezione.

151
00:10:12,230 --> 00:10:15,500
‫Ci vediamo nel prossimo in cui useremo metodi virtuali con rabbia.

