‫Quindi in questa lezione parleremo del metodo virtuale in C++.
‫L'abbiamo già visto, l'abbiamo usato, ma l'abbiamo capito fino in fondo?
‫Lasciaci vedere.
‫Quindi l'idea di un metodo virtuale è che ci permette di sovrascrivere le funzioni in una classe base.
‫L'abbiamo visto con cose come Begin, Play e Take in Unreal.
‫Ma andiamo oltre e comprendiamo perché sono contrassegnati come virtuali.
‫Ci consente di modificare la funzionalità in quella classe base e fa qualcosa chiamato Dynamic Dispatch, di cui parleremo tra
‫un secondo per capire cosa significa veramente e perché i metodi virtuali non sono la
‫funzionalità predefinita in C++ come lo sono in molte altre lingue, come C Sharp.
‫Quindi diamo un'occhiata a questo.
‫Lo farò nel sito Web CPP dot SH in modo che non siamo affatto in Unreal qui.
‫Stiamo solo esaminando la funzionalità C++ grezza in modo che tu possa capire questa funzionalità del linguaggio e
‫come funziona.
‫Ora, la prima cosa che farò qui è semplicemente andare avanti e chiarire il metodo principale.
‫E nel nostro caso d'uso penseremo a una classe per le armi, visto che questo è un caso d'uso molto comune per
‫i giochi.
‫Quindi diamo un'occhiata a una classe, raffreddiamo la pistola in modo abbastanza diretto e quindi faremo in modo che
‫il corpo di questa classe sia pubblico e un metodo di tiro vuoto.
‫E ho intenzione di andare avanti e dichiarare il corpo di questo metodo di ripresa proprio qui in linea per mantenere le
‫cose super semplici.
‫A proposito, puoi farlo se non l'hai mai visto prima.
‫Ma in generale, vogliamo fare le cose in un file C++ separato per mantenere le cose separate, per rendere i tempi di
‫compilazione più rapidi e così via.
‫Ma qui, dove è solo un esempio di giocattolo, va bene.
‫Quindi faremo una prova SD.
‫Quindi usando C++ come roba di stringa di output e andremo a fare il botto.
‫Fondamentalmente quando chiamiamo questo metodo e poi andremo a fine riga.
‫E questo è il corpo del nostro metodo dello scivolo.
‫E possiamo chiudere la classe in cui la parentesi graffa e il punto e virgola.
‫Quindi andiamo avanti e usiamo effettivamente questa classe.
‫Creerò una variabile my gun in main e chiamerò il mio gun dot shoot e vediamo se tutto
‫funziona qui come dovrebbe.
‫Premi il pulsante Esegui e sbatti.
‫Sta chiamando il metodo come ci aspetteremmo.
‫Ora cosa succede se voglio estendere la mia pistola e forse fare un fucile o una pistola che si chiama pistola.
‫Quindi la pistola di classe è ereditata dalla pistola, il che farebbe così.
‫E se non l'avevi visto prima perché probabilmente non l'hai scritto necessariamente prima, fai
‫un'eredità pubblica dalle armi in modo che le altre classi possano vedere che erediti dalle armi.
‫E poi, nella sezione pubblica, vogliamo forse creare il nostro metodo di tiro per la pistola che prevale
‫su questa funzionalità.
‫E invece di stampare il botto alla fine qui vogliamo stampare la pillola perché è una pistola più piccola, fa un suono
‫più piccolo e questo è il nostro metodo di tiro lì.
‫E chiudiamo la classe lì.
‫E quello che vogliamo fare è creare noi stessi una pistola.
‫Quindi pistola la mia pistola nel metodo principale qui.
‫E poiché questi esistono solo qui, proprio sul metodo principale, non stiamo usando i puntatori ad essi.
‫Ecco perché qui stiamo usando l'operatore punto invece della freccia.
‫Quindi il mio tiro con la pistola.
‫Vediamo cosa fa.
‫Mi aspetto che stampi ppu, cosa che fa.
‫Freddo.
‫Ok, quindi rimuoviamo i nostri metodi che stanno chiamando.
‫Sparate direttamente su questi e vediamo come si comporterebbero le cose con un puntatore.
‫Quindi creerò un puntatore pistola chiamato gun.
‫Peter.
‫E nella riga successiva potrei farlo sulla stessa riga, ma per semplicità, lo farò nella riga
‫successiva.
‫Imposterò il puntatore della pistola in modo che punti all'indirizzo dell'indirizzo dell'operatore, l'indirizzo della
‫variabile my gun.
‫E poi, poiché è un puntatore, dobbiamo usare l'operatore freccia per chiamare il metodo di tiro.
‫Quindi chiamerò sparare sulla mia pistola.
‫Facciamo clic su Esegui e otteniamo il botto come risultato lì.
‫Freddo.
‫Ora cosa succede se faccio la stessa cosa?
‫Ma invece di impostare la pistola puntata verso la mia pistola, l'ho impostata in modo che punti verso la mia pistola.
‫Andiamo avanti e premiamo corri ora.
‫Bene.
‫È un comportamento interessante lì.
‫Quello che sta succedendo qui è chiamare questo primo metodo in entrambi i casi.
‫Allora perché questo secondo metodo di ripresa non è stato chiamato?
‫Abbiamo una pistola qui come puntatore.
‫Bene, quello che succede se non hai un metodo virtuale è che per impostazione predefinita, C++ utilizzerà il tipo del tuo
‫puntatore, che è un puntatore di pistola.
‫Ricorda, utilizzerà quel tipo per trovare il metodo da chiamare.
‫Quindi andrà a chiamare questo metodo di tiro in alto piuttosto che il metodo sovrascritto nella pistola.
‫Affinché possa chiamare il metodo sovrascritto in pistola, dovrebbe chiamare.
‫Dovrebbe avere un puntatore di tipo pistola.
‫Ora va bene.
‫E puoi capire perché lo fanno.
‫È per l'efficienza.
‫C++ è tutto incentrato sull'efficienza.
‫Se qualcosa costerà di più quando viene compilato, quando viene eseguito, C++ non lo farà per impostazione predefinita a meno che tu
‫non lo richieda.
‫Quindi è molto facile per C++ cercare e dire, Bene, questo è un puntatore della pistola, quindi chiamerò questo metodo del
‫puntatore della pistola.
‫Ed è qui che entra in gioco Dynamic Dispatch.
‫Questo termine di fantasia fondamentalmente significa che non vogliamo che lo faccia.
‫Quello che vogliamo che faccia è dire, aspetta un secondo, cosa è effettivamente memorizzato in quel puntatore di pistola?
‫Qual è il vero tipo lì?
‫E il vero tipo di cui ci rendiamo conto è che è un tipo di pistola.
‫E quindi dobbiamo chiederci, c'è un metodo per quel tipo che è sovrascritto?
‫E sì, c'è.
‫Quindi, come diamo a C++ il permesso di essere solo un po' meno efficiente e ci diamo la possibilità di
‫eseguire l'override senza dover modificare quel tipo di puntatore, il che non è sempre necessariamente possibile.
‫In effetti, in molti casi non è possibile, come nel caso di una classe attiva
‫personalizzata.
‫Unreal non ha il puntatore impostato per puntare alla tua classe particolare che richiederebbe loro di cambiare l'intero
‫motore ogni volta che introduci una nuova classe.
‫No, non è possibile.
‫Hanno un puntatore a qualcosa di tipo atto da recitare.
‫Quindi, quando chiamano Begin Play, volevi chiamare il tuo metodo Begin Play.
‫Quindi deve essere virtuale.
‫E questa è la chiave qui.
‫Se rimaniamo virtual davanti al metodo nella classe genitore, questo ora segnala a C++ che si blocca per un secondo, se sto
‫chiamando shoot su un puntatore di tipo gun pointer, devo verificare che non lo sia, ad esempio , una pistola
‫e che questo metodo di tiro è stato ignorato.
‫Quindi, se andiamo avanti e premiamo corri ora, puoi vedere che prendiamo il botto e poi il pue.
‫Quindi funziona come ci aspetteremmo con l'invio dinamico.
‫E questo è il termine per questa cosa in cui fondamentalmente intendiamo solo controllare che tipo di tipo è effettivamente
‫contenuto nel puntatore e chiamare il metodo pertinente.
‫Ora c'è un po' di sintassi in più che ci vedrai usare spesso, e questa è la parola
‫chiave override.
‫E lo metti dopo un metodo che stai cercando di ignorare come virtuale.
‫E fondamentalmente la parola chiave override non è strettamente necessaria, né lo è mettere di nuovo virtuale contro qualcosa
‫nella classe figlia di una pistola.
‫Quindi non devi mettere virtuale, ma non fa male farlo.
‫Ma l'override è particolarmente utile perché ci consente di assicurarci di avere la nostra denominazione
‫corretta.
‫Quindi, se premo Esegui, tutto funziona come prima quando ho l'override.
‫Ma supponiamo di aver erroneamente sbagliato il nome di questo metodo, quindi non eseguo l'override.
‫E l'avevo chiamato uno sparatutto, per esempio.
‫Ho sbagliato a copiare il nome.
‫L'ho digitato invece di copiarlo.
‫Se premo Esegui ora, vedi, abbiamo di nuovo lo stesso errore perché stiamo cercando di raffreddare per sparare.
‫Lo abbiamo erroneamente sovrascritto in modo errato.
‫Sta andando botto, botto.
‫Quindi il modo in cui potrei evitarlo è dicendo: Bene, sto cercando di ignorare qualcosa.
‫Quindi ho inserito la mia parola chiave di override qui, e se provo a compilarla ora, puoi vedere che sta dicendo
‫che lo sparatutto è contrassegnato come override, ma non c'è nessun metodo, nessun metodo virtuale per me da sovrascrivere, nel qual
‫caso posso andare , Oh sì, l'ho digitato male.
‫Quindi andrò avanti e correggerò il mio codice e lo farò tornare per sparare.
‫E ora funziona come previsto.
‫Quindi è solo un po' di sicurezza in più inserendo quell'override lì e istantaneamente questo.
‫Ci proteggerebbe anche dal caso in cui la cosa che stiamo cercando di ignorare non è virtuale.
‫Se provo a farlo, puoi vedere che sta dicendo che è contrassegnato come override, ma non
‫sovrascrive perché quella classe genitore non ha una funzione virtuale per le riprese.
‫Quindi si spera che questo ti stia dando una panoramica di come C++ usa e implementa le funzioni virtuali e
‫perché dobbiamo essere così espliciti su di esse.
‫Ora, pensiamo ad altri casi d'uso per le funzioni virtuali in generale.
‫Ne abbiamo già visti alcuni dal motore.
‫Dove hai mai visto il virtuale usato prima?
‫Dove puoi immaginare di usarlo?
‫Abbiamo appena visto un esempio di caso d'uso in cui potresti avere una pistola e diverse sostituzioni di quella che
‫implementano le riprese in modi diversi.
‫In quale altro modo potresti immaginare di utilizzare funzioni virtuali per sovrascrivere la funzionalità nelle classi padre?
‫Quando hai pensato a una risposta a queste due domande, vai e segui il link alle
‫discussioni in questa lezione e pubblica la tua risposta.
‫Visualizzano i casi d'uso e i luoghi in cui li hai usati prima e vedono cosa hanno inventato altre persone.
‫Forse questo ti aiuterà a consolidare la tua comprensione dei metodi virtuali.
‫Questo è tutto per questa lezione.
‫Ci vediamo nel prossimo in cui useremo metodi virtuali con rabbia.